Skip to main content

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>(
32        &'_ self,
33    ) -> Result<DecodedJwt<'_, C>, DecodeError>;
34
35    /// Decodes a JWT.
36    fn to_decoded_jwt(&'_ self) -> Result<DecodedJwt<'_>, DecodeError> {
37        self.to_decoded_custom_jwt::<AnyClaims>()
38    }
39
40    /// Verify the JWS signature.
41    ///
42    /// This check the signature and the validity of registered claims.
43    #[allow(async_fn_in_trait)]
44    async fn verify_jwt<V>(&self, verifier: &V) -> Result<Verification, ProofValidationError>
45    where
46        V: ResolverProvider + DateTimeProvider,
47        V::Resolver: JWKResolver,
48    {
49        self.to_decoded_jwt()?.verify(verifier).await
50    }
51}
52
53/// JWT consuming decoding.
54pub trait IntoDecodedJwt: Sized {
55    /// Decodes a JWT with custom claims.
56    fn into_decoded_custom_jwt<C: DeserializeOwned>(
57        self,
58    ) -> Result<DecodedJwt<'static, C>, DecodeError>;
59
60    fn into_decoded_jwt(self) -> Result<DecodedJwt<'static>, DecodeError> {
61        self.into_decoded_custom_jwt::<AnyClaims>()
62    }
63}
64
65impl ToDecodedJwt for JwsSlice {
66    fn to_decoded_custom_jwt<C: DeserializeOwned>(
67        &'_ self,
68    ) -> Result<DecodedJwt<'_, C>, DecodeError> {
69        self.decode()?
70            .try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
71    }
72}
73
74impl ToDecodedJwt for JwsStr {
75    fn to_decoded_custom_jwt<C: DeserializeOwned>(
76        &'_ self,
77    ) -> Result<DecodedJwt<'_, C>, DecodeError> {
78        JwsSlice::to_decoded_custom_jwt(self)
79    }
80}
81
82impl ToDecodedJwt for JwsVec {
83    fn to_decoded_custom_jwt<C: DeserializeOwned>(
84        &'_ self,
85    ) -> Result<DecodedJwt<'_, C>, DecodeError> {
86        JwsSlice::to_decoded_custom_jwt(self)
87    }
88}
89
90impl IntoDecodedJwt for JwsVec {
91    fn into_decoded_custom_jwt<C: DeserializeOwned>(
92        self,
93    ) -> Result<DecodedJwt<'static, C>, DecodeError> {
94        self.into_decoded()?
95            .try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
96    }
97}
98
99impl ToDecodedJwt for JwsString {
100    fn to_decoded_custom_jwt<C: DeserializeOwned>(
101        &'_ self,
102    ) -> Result<DecodedJwt<'_, C>, DecodeError> {
103        JwsSlice::to_decoded_custom_jwt(self)
104    }
105}
106
107impl IntoDecodedJwt for JwsString {
108    fn into_decoded_custom_jwt<C: DeserializeOwned>(
109        self,
110    ) -> Result<DecodedJwt<'static, C>, DecodeError> {
111        self.into_decoded()?
112            .try_map(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
113    }
114}