jsonwebtoken_rustcrypto/
decoding.rs

1use rsa::RsaPublicKey;
2use serde::de::DeserializeOwned;
3
4use crate::crypto::verify;
5use crate::errors::{new_error, ErrorKind, Result};
6use crate::header::Header;
7// use crate::pem::decoder::PemEncodedKey;
8use crate::serialization::from_jwt_part_claims;
9use crate::validation::{validate, Validation};
10
11use base64::{engine::general_purpose::STANDARD, Engine};
12/// The return type of a successful call to [decode](fn.decode.html).
13#[derive(Debug)]
14pub struct TokenData<T> {
15    /// The decoded JWT header
16    pub header: Header,
17    /// The decoded JWT claims
18    pub claims: T,
19}
20
21/// Takes the result of a rsplit and ensure we only get 2 parts
22/// Errors if we don't
23macro_rules! expect_two {
24    ($iter:expr) => {{
25        let mut i = $iter;
26        match (i.next(), i.next(), i.next()) {
27            (Some(first), Some(second), None) => (first, second),
28            _ => return Err(new_error(ErrorKind::InvalidToken)),
29        }
30    }};
31}
32
33/// All the different kind of keys we can use to decode a JWT
34/// This key can be re-used so make sure you only initialize it once if you can for better performance
35#[derive(Debug, Clone, PartialEq)]
36pub enum DecodingKey {
37    Hmac(Vec<u8>),
38    Rsa(rsa::RsaPublicKey),
39    // EcPkcs8(Vec<u8>),
40}
41
42impl DecodingKey {
43    /// If you're using HMAC, use this.
44    pub fn from_hmac_secret(secret: &[u8]) -> Self {
45        DecodingKey::Hmac(secret.to_vec())
46    }
47
48    /// If you're using HMAC with a base64 encoded, use this.
49    pub fn from_base64_hmac_secret(secret: &str) -> Result<Self> {
50        Ok(DecodingKey::Hmac(STANDARD.decode(secret)?))
51    }
52
53    pub fn from_rsa(key: rsa::RsaPublicKey) -> Result<Self> {
54        Ok(DecodingKey::Rsa(key))
55    }
56
57    /// Convenience function for JWKS implementors
58    pub fn from_rsa_components(n: &str, e: &str) -> Result<Self> {
59        use crate::serialization::b64_decode;
60        let n = rsa::BigUint::from_bytes_be(&b64_decode(n)?);
61        let e = rsa::BigUint::from_bytes_be(&b64_decode(e)?);
62        Ok(DecodingKey::Rsa(
63            RsaPublicKey::new(n, e).map_err(|_| new_error(ErrorKind::InvalidKeyFormat))?,
64        ))
65    }
66}
67
68/// Decode and validate a JWT
69///
70/// If the token or its signature is invalid or the claims fail validation, it will return an error.
71///
72/// ```rust
73/// use serde::{Deserialize, Serialize};
74/// use jsonwebtoken_rustcrypto::{decode, DecodingKey, Validation, Algorithm};
75///
76/// #[derive(Debug, Serialize, Deserialize)]
77/// struct Claims {
78///    sub: String,
79///    company: String
80/// }
81///
82/// let token = "a.jwt.token".to_string();
83/// // Claims is a struct that implements Deserialize
84/// let token_message = decode::<Claims>(&token, &DecodingKey::from_hmac_secret("secret".as_ref()), &Validation::new(Algorithm::HS256));
85/// ```
86pub fn decode<T: DeserializeOwned>(
87    token: &str,
88    key: &DecodingKey,
89    validation: &Validation,
90) -> Result<TokenData<T>> {
91    let (signature, message) = expect_two!(token.rsplitn(2, '.'));
92    let (claims, header) = expect_two!(message.rsplitn(2, '.'));
93    let header = Header::from_encoded(header)?;
94
95    if !validation.algorithms.is_empty() & !&validation.algorithms.contains(&header.alg) {
96        return Err(new_error(ErrorKind::InvalidAlgorithm));
97    }
98
99    if !verify(signature, message, key, header.alg)? {
100        return Err(new_error(ErrorKind::InvalidSignature));
101    }
102
103    let (decoded_claims, claims_map): (T, _) = from_jwt_part_claims(claims)?;
104    validate(&claims_map, validation)?;
105
106    Ok(TokenData { header, claims: decoded_claims })
107}
108
109/// Decode a JWT without any signature verification/validations.
110///
111/// NOTE: Do not use this unless you know what you are doing! If the token's signature is invalid, it will *not* return an error.
112///
113/// ```rust
114/// use serde::{Deserialize, Serialize};
115/// use jsonwebtoken_rustcrypto::{dangerous_insecure_decode, Validation, Algorithm};
116///
117/// #[derive(Debug, Serialize, Deserialize)]
118/// struct Claims {
119///     sub: String,
120///     company: String
121/// }
122///
123/// let token = "a.jwt.token".to_string();
124/// // Claims is a struct that implements Deserialize
125/// let token_message = dangerous_insecure_decode::<Claims>(&token);
126/// ```
127pub fn dangerous_insecure_decode<T: DeserializeOwned>(token: &str) -> Result<TokenData<T>> {
128    let (_, message) = expect_two!(token.rsplitn(2, '.'));
129    let (claims, header) = expect_two!(message.rsplitn(2, '.'));
130    let header = Header::from_encoded(header)?;
131
132    let (decoded_claims, _): (T, _) = from_jwt_part_claims(claims)?;
133
134    Ok(TokenData { header, claims: decoded_claims })
135}
136
137/// Decode and validate a JWT without any signature verification.
138///
139/// If the token is invalid or the claims fail validation, it will return an error.
140///
141/// NOTE: Do not use this unless you know what you are doing! If the token's signature is invalid, it will *not* return an error.
142///
143/// ```rust
144/// use serde::{Deserialize, Serialize};
145/// use jsonwebtoken_rustcrypto::{dangerous_insecure_decode_with_validation, Validation, Algorithm};
146///
147/// #[derive(Debug, Serialize, Deserialize)]
148/// struct Claims {
149///    sub: String,
150///    company: String
151/// }
152///
153/// let token = "a.jwt.token";
154/// // Claims is a struct that implements Deserialize
155/// let token_message = dangerous_insecure_decode_with_validation::<Claims>(&token, &Validation::new(Algorithm::HS256));
156/// ```
157pub fn dangerous_insecure_decode_with_validation<T: DeserializeOwned>(
158    token: &str,
159    validation: &Validation,
160) -> Result<TokenData<T>> {
161    let (_, message) = expect_two!(token.rsplitn(2, '.'));
162    let (claims, header) = expect_two!(message.rsplitn(2, '.'));
163    let header = Header::from_encoded(header)?;
164
165    if !validation.algorithms.is_empty() & !&validation.algorithms.contains(&header.alg) {
166        return Err(new_error(ErrorKind::InvalidAlgorithm));
167    }
168
169    let (decoded_claims, claims_map): (T, _) = from_jwt_part_claims(claims)?;
170    validate(&claims_map, validation)?;
171
172    Ok(TokenData { header, claims: decoded_claims })
173}
174
175/// Decode a JWT without any signature verification/validations. DEPRECATED.
176#[deprecated(
177    note = "This function has been renamed to `dangerous_insecure_decode` and will be removed in a later version."
178)]
179pub fn dangerous_unsafe_decode<T: DeserializeOwned>(token: &str) -> Result<TokenData<T>> {
180    dangerous_insecure_decode(token)
181}
182
183/// Decode a JWT without any signature verification/validations and return its [Header](struct.Header.html).
184///
185/// If the token has an invalid format (ie 3 parts separated by a `.`), it will return an error.
186///
187/// ```rust
188/// use jsonwebtoken_rustcrypto::decode_header;
189///
190/// let token = "a.jwt.token".to_string();
191/// let header = decode_header(&token);
192/// ```
193pub fn decode_header(token: &str) -> Result<Header> {
194    let (_, message) = expect_two!(token.rsplitn(2, '.'));
195    let (_, header) = expect_two!(message.rsplitn(2, '.'));
196    Header::from_encoded(header)
197}