use serde::de::DeserializeOwned;
use ssi_claims_core::{DateTimeProvider, ProofValidationError, ResolverProvider, Verification};
use ssi_jwk::JWKResolver;
use ssi_jws::{DecodeError as JWSDecodeError, DecodedJws, JwsSlice, JwsStr, JwsString, JwsVec};
use crate::{AnyClaims, JWTClaims};
#[derive(Debug, thiserror::Error)]
pub enum DecodeError {
#[error("invalid JWS: {0}")]
JWS(#[from] JWSDecodeError),
#[error("invalid JWT claims: {0}")]
Claims(#[from] serde_json::Error),
}
impl From<DecodeError> for ProofValidationError {
fn from(value: DecodeError) -> Self {
Self::InvalidInputData(value.to_string())
}
}
pub type DecodedJwt<'a, T = AnyClaims> = DecodedJws<'a, JWTClaims<T>>;
pub trait ToDecodedJwt {
fn to_decoded_custom_jwt<C: DeserializeOwned>(
&'_ self,
) -> Result<DecodedJwt<'_, C>, DecodeError>;
fn to_decoded_jwt(&'_ self) -> Result<DecodedJwt<'_>, DecodeError> {
self.to_decoded_custom_jwt::<AnyClaims>()
}
#[allow(async_fn_in_trait)]
async fn verify_jwt<V>(&self, verifier: &V) -> Result<Verification, ProofValidationError>
where
V: ResolverProvider + DateTimeProvider,
V::Resolver: JWKResolver,
{
self.to_decoded_jwt()?.verify(verifier).await
}
}
pub trait IntoDecodedJwt: Sized {
fn into_decoded_custom_jwt<C: DeserializeOwned>(
self,
) -> Result<DecodedJwt<'static, C>, DecodeError>;
fn into_decoded_jwt(self) -> Result<DecodedJwt<'static>, DecodeError> {
self.into_decoded_custom_jwt::<AnyClaims>()
}
}
impl ToDecodedJwt for JwsSlice {
fn to_decoded_custom_jwt<C: DeserializeOwned>(
&'_ self,
) -> Result<DecodedJwt<'_, C>, DecodeError> {
self.decode()?
.try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
}
}
impl ToDecodedJwt for JwsStr {
fn to_decoded_custom_jwt<C: DeserializeOwned>(
&'_ self,
) -> Result<DecodedJwt<'_, C>, DecodeError> {
JwsSlice::to_decoded_custom_jwt(self)
}
}
impl ToDecodedJwt for JwsVec {
fn to_decoded_custom_jwt<C: DeserializeOwned>(
&'_ self,
) -> Result<DecodedJwt<'_, C>, DecodeError> {
JwsSlice::to_decoded_custom_jwt(self)
}
}
impl IntoDecodedJwt for JwsVec {
fn into_decoded_custom_jwt<C: DeserializeOwned>(
self,
) -> Result<DecodedJwt<'static, C>, DecodeError> {
self.into_decoded()?
.try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
}
}
impl ToDecodedJwt for JwsString {
fn to_decoded_custom_jwt<C: DeserializeOwned>(
&'_ self,
) -> Result<DecodedJwt<'_, C>, DecodeError> {
JwsSlice::to_decoded_custom_jwt(self)
}
}
impl IntoDecodedJwt for JwsString {
fn into_decoded_custom_jwt<C: DeserializeOwned>(
self,
) -> Result<DecodedJwt<'static, C>, DecodeError> {
self.into_decoded()?
.try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
}
}