Skip to main content

jsonwebtoken/
errors.rs

1use std::error::Error as StdError;
2use std::fmt;
3use std::result;
4use std::sync::Arc;
5
6/// A constructor for `Error`.
7/// Intended for use in custom crypto providers.
8pub fn new_error(kind: ErrorKind) -> Error {
9    Error(Box::new(kind))
10}
11
12/// A type alias for `Result<T, jsonwebtoken::errors::Error>`.
13pub type Result<T> = result::Result<T, Error>;
14
15/// An error that can occur when encoding/decoding JWTs
16#[derive(Clone, Debug, Eq, PartialEq)]
17pub struct Error(Box<ErrorKind>);
18
19impl Error {
20    /// Return the specific type of this error.
21    pub fn kind(&self) -> &ErrorKind {
22        &self.0
23    }
24
25    /// Unwrap this error into its underlying type.
26    pub fn into_kind(self) -> ErrorKind {
27        *self.0
28    }
29}
30
31/// The specific type of an error.
32///
33/// This enum may grow additional variants, the `#[non_exhaustive]`
34/// attribute makes sure clients don't count on exhaustive matching.
35/// (Otherwise, adding a new variant could break existing code.)
36#[non_exhaustive]
37#[derive(Clone, Debug)]
38pub enum ErrorKind {
39    /// When a token doesn't have a valid JWT shape
40    InvalidToken,
41    /// When the signature doesn't match
42    InvalidSignature,
43    /// When the secret given is not a valid ECDSA key
44    InvalidEcdsaKey,
45    /// When the secret given is not a valid EdDSA key
46    InvalidEddsaKey,
47    /// When the secret given is not a valid RSA key
48    InvalidRsaKey(String),
49    /// We could not sign with the given key
50    RsaFailedSigning,
51    /// Signing failed
52    Signing(String),
53    /// When the algorithm from string doesn't match the one passed to `from_str`
54    InvalidAlgorithmName,
55    /// When a key is provided with an invalid format
56    InvalidKeyFormat,
57
58    // Validation errors
59    /// When a claim required by the validation is not present
60    MissingRequiredClaim(String),
61    /// When a claim has an invalid format (eg string instead of integer)
62    InvalidClaimFormat(String),
63    /// When a token’s `exp` claim indicates that it has expired
64    ExpiredSignature,
65    /// When a token’s `iss` claim does not match the expected issuer
66    InvalidIssuer,
67    /// When a token’s `aud` claim does not match one of the expected audience values
68    InvalidAudience,
69    /// When a token’s `sub` claim does not match one of the expected subject values
70    InvalidSubject,
71    /// When a token’s `nbf` claim represents a time in the future
72    ImmatureSignature,
73    /// When the algorithm in the header doesn't match the one passed to `decode` or the encoding/decoding key
74    /// used doesn't match the alg requested
75    InvalidAlgorithm,
76    /// When the Validation struct does not contain at least 1 algorithm
77    MissingAlgorithm,
78
79    // 3rd party errors
80    /// An error happened when decoding some base64 text
81    Base64(base64::DecodeError),
82    /// An error happened while serializing/deserializing JSON
83    Json(Arc<serde_json::Error>),
84    /// Some of the text was invalid UTF-8
85    Utf8(::std::string::FromUtf8Error),
86    /// An error happened in a custom provider
87    Provider(String),
88}
89
90impl StdError for Error {
91    fn cause(&self) -> Option<&dyn StdError> {
92        match &*self.0 {
93            ErrorKind::InvalidToken => None,
94            ErrorKind::InvalidSignature => None,
95            ErrorKind::InvalidEcdsaKey => None,
96            ErrorKind::InvalidEddsaKey => None,
97            ErrorKind::RsaFailedSigning => None,
98            ErrorKind::Signing(_) => None,
99            ErrorKind::InvalidRsaKey(_) => None,
100            ErrorKind::ExpiredSignature => None,
101            ErrorKind::MissingAlgorithm => None,
102            ErrorKind::MissingRequiredClaim(_) => None,
103            ErrorKind::InvalidClaimFormat(_) => None,
104            ErrorKind::InvalidIssuer => None,
105            ErrorKind::InvalidAudience => None,
106            ErrorKind::InvalidSubject => None,
107            ErrorKind::ImmatureSignature => None,
108            ErrorKind::InvalidAlgorithm => None,
109            ErrorKind::InvalidAlgorithmName => None,
110            ErrorKind::InvalidKeyFormat => None,
111            ErrorKind::Base64(err) => Some(err),
112            ErrorKind::Json(err) => Some(err.as_ref()),
113            ErrorKind::Utf8(err) => Some(err),
114            ErrorKind::Provider(_) => None,
115        }
116    }
117}
118
119impl fmt::Display for Error {
120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121        match &*self.0 {
122            ErrorKind::InvalidToken
123            | ErrorKind::InvalidSignature
124            | ErrorKind::InvalidEcdsaKey
125            | ErrorKind::ExpiredSignature
126            | ErrorKind::RsaFailedSigning
127            | ErrorKind::MissingAlgorithm
128            | ErrorKind::InvalidIssuer
129            | ErrorKind::InvalidAudience
130            | ErrorKind::InvalidSubject
131            | ErrorKind::ImmatureSignature
132            | ErrorKind::InvalidAlgorithm
133            | ErrorKind::InvalidKeyFormat
134            | ErrorKind::InvalidEddsaKey
135            | ErrorKind::InvalidAlgorithmName => write!(f, "{:?}", self.0),
136            ErrorKind::MissingRequiredClaim(c) => write!(f, "Missing required claim: {}", c),
137            ErrorKind::InvalidClaimFormat(c) => write!(f, "Invalid format for claim: {}", c),
138            ErrorKind::InvalidRsaKey(msg) => write!(f, "RSA key invalid: {}", msg),
139            ErrorKind::Signing(msg) => write!(f, "Signing failed: {}", msg),
140            ErrorKind::Json(err) => write!(f, "JSON error: {}", err),
141            ErrorKind::Utf8(err) => write!(f, "UTF-8 error: {}", err),
142            ErrorKind::Base64(err) => write!(f, "Base64 error: {}", err),
143            ErrorKind::Provider(msg) => write!(f, "Custom provider error: {}", msg),
144        }
145    }
146}
147
148impl PartialEq for ErrorKind {
149    fn eq(&self, other: &Self) -> bool {
150        format!("{:?}", self) == format!("{:?}", other)
151    }
152}
153
154// Equality of ErrorKind is an equivalence relation: it is reflexive, symmetric and transitive.
155impl Eq for ErrorKind {}
156
157impl From<base64::DecodeError> for Error {
158    fn from(err: base64::DecodeError) -> Error {
159        new_error(ErrorKind::Base64(err))
160    }
161}
162
163impl From<serde_json::Error> for Error {
164    fn from(err: serde_json::Error) -> Error {
165        new_error(ErrorKind::Json(Arc::new(err)))
166    }
167}
168
169impl From<::std::string::FromUtf8Error> for Error {
170    fn from(err: ::std::string::FromUtf8Error) -> Error {
171        new_error(ErrorKind::Utf8(err))
172    }
173}
174
175impl From<ErrorKind> for Error {
176    fn from(kind: ErrorKind) -> Error {
177        new_error(kind)
178    }
179}
180
181impl From<signature::Error> for Error {
182    fn from(err: signature::Error) -> Error {
183        new_error(ErrorKind::Signing(err.to_string()))
184    }
185}
186
187#[cfg(test)]
188mod tests {
189    use wasm_bindgen_test::wasm_bindgen_test;
190
191    use super::*;
192
193    #[test]
194    #[wasm_bindgen_test]
195    fn test_error_rendering() {
196        assert_eq!(
197            "InvalidAlgorithmName",
198            Error::from(ErrorKind::InvalidAlgorithmName).to_string()
199        );
200    }
201}