ssi_jwt/
decoding.rs

1use serde::de::DeserializeOwned;
2use ssi_claims_core::{DateTimeProvider, ProofValidationError, ResolverProvider, Verification};
3use ssi_jwk::JWKResolver;
4use ssi_jws::{DecodeError as JWSDecodeError, DecodedJws, JwsSlice, JwsStr, JwsString, JwsVec};
5
6use crate::{AnyClaims, JWTClaims};
7
8#[derive(Debug, thiserror::Error)]
9pub enum DecodeError {
10    #[error("invalid JWS: {0}")]
11    JWS(#[from] JWSDecodeError),
12
13    #[error("invalid JWT claims: {0}")]
14    Claims(#[from] serde_json::Error),
15}
16
17impl From<DecodeError> for ProofValidationError {
18    fn from(value: DecodeError) -> Self {
19        Self::InvalidInputData(value.to_string())
20    }
21}
22
23/// Decoded JWT.
24///
25/// By definition this is a decoded JWS with JWT claims as payload.
26pub type DecodedJwt<'a, T = AnyClaims> = DecodedJws<'a, JWTClaims<T>>;
27
28/// JWT borrowing decoding.
29pub trait ToDecodedJwt {
30    /// Decodes a JWT with custom claims.
31    fn to_decoded_custom_jwt<C: DeserializeOwned>(&self) -> Result<DecodedJwt<C>, DecodeError>;
32
33    /// Decodes a JWT.
34    fn to_decoded_jwt(&self) -> Result<DecodedJwt, DecodeError> {
35        self.to_decoded_custom_jwt::<AnyClaims>()
36    }
37
38    /// Verify the JWS signature.
39    ///
40    /// This check the signature and the validity of registered claims.
41    #[allow(async_fn_in_trait)]
42    async fn verify_jwt<V>(&self, verifier: &V) -> Result<Verification, ProofValidationError>
43    where
44        V: ResolverProvider + DateTimeProvider,
45        V::Resolver: JWKResolver,
46    {
47        self.to_decoded_jwt()?.verify(verifier).await
48    }
49}
50
51/// JWT consuming decoding.
52pub trait IntoDecodedJwt: Sized {
53    /// Decodes a JWT with custom claims.
54    fn into_decoded_custom_jwt<C: DeserializeOwned>(
55        self,
56    ) -> Result<DecodedJwt<'static, C>, DecodeError>;
57
58    fn into_decoded_jwt(self) -> Result<DecodedJwt<'static>, DecodeError> {
59        self.into_decoded_custom_jwt::<AnyClaims>()
60    }
61}
62
63impl ToDecodedJwt for JwsSlice {
64    fn to_decoded_custom_jwt<C: DeserializeOwned>(&self) -> Result<DecodedJwt<C>, DecodeError> {
65        self.decode()?
66            .try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
67    }
68}
69
70impl ToDecodedJwt for JwsStr {
71    fn to_decoded_custom_jwt<C: DeserializeOwned>(&self) -> Result<DecodedJwt<C>, DecodeError> {
72        JwsSlice::to_decoded_custom_jwt(self)
73    }
74}
75
76impl ToDecodedJwt for JwsVec {
77    fn to_decoded_custom_jwt<C: DeserializeOwned>(&self) -> Result<DecodedJwt<C>, DecodeError> {
78        JwsSlice::to_decoded_custom_jwt(self)
79    }
80}
81
82impl IntoDecodedJwt for JwsVec {
83    fn into_decoded_custom_jwt<C: DeserializeOwned>(
84        self,
85    ) -> Result<DecodedJwt<'static, C>, DecodeError> {
86        self.into_decoded()?
87            .try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
88    }
89}
90
91impl ToDecodedJwt for JwsString {
92    fn to_decoded_custom_jwt<C: DeserializeOwned>(&self) -> Result<DecodedJwt<C>, DecodeError> {
93        JwsSlice::to_decoded_custom_jwt(self)
94    }
95}
96
97impl IntoDecodedJwt for JwsString {
98    fn into_decoded_custom_jwt<C: DeserializeOwned>(
99        self,
100    ) -> Result<DecodedJwt<'static, C>, DecodeError> {
101        self.into_decoded()?
102            .try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
103    }
104}