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 the algorithm is not supported
56    UnsupportedAlgorithm,
57    /// When a key is provided with an invalid format
58    InvalidKeyFormat,
59
60    // Validation errors
61    /// When a claim required by the validation is not present
62    MissingRequiredClaim(String),
63    /// When a claim has an invalid format (eg string instead of integer)
64    InvalidClaimFormat(String),
65    /// When a token’s `exp` claim indicates that it has expired
66    ExpiredSignature,
67    /// When a token’s `iss` claim does not match the expected issuer
68    InvalidIssuer,
69    /// When a token’s `aud` claim does not match one of the expected audience values
70    InvalidAudience,
71    /// When a token’s `sub` claim does not match one of the expected subject values
72    InvalidSubject,
73    /// When a token’s `nbf` claim represents a time in the future
74    ImmatureSignature,
75    /// When the algorithm in the header doesn't match the one passed to `decode` or the encoding/decoding key
76    /// used doesn't match the alg requested
77    InvalidAlgorithm,
78    /// When the Validation struct does not contain at least 1 algorithm
79    MissingAlgorithm,
80
81    // 3rd party errors
82    /// An error happened when decoding some base64 text
83    Base64(base64::DecodeError),
84    /// An error happened while serializing/deserializing JSON
85    Json(Arc<serde_json::Error>),
86    /// Some of the text was invalid UTF-8
87    Utf8(::std::string::FromUtf8Error),
88    /// An error happened in a custom provider
89    Provider(String),
90}
91
92impl StdError for Error {
93    fn cause(&self) -> Option<&dyn StdError> {
94        match &*self.0 {
95            ErrorKind::InvalidToken => None,
96            ErrorKind::InvalidSignature => None,
97            ErrorKind::InvalidEcdsaKey => None,
98            ErrorKind::InvalidEddsaKey => None,
99            ErrorKind::RsaFailedSigning => None,
100            ErrorKind::Signing(_) => None,
101            ErrorKind::InvalidRsaKey(_) => None,
102            ErrorKind::ExpiredSignature => None,
103            ErrorKind::MissingAlgorithm => None,
104            ErrorKind::MissingRequiredClaim(_) => None,
105            ErrorKind::InvalidClaimFormat(_) => None,
106            ErrorKind::InvalidIssuer => None,
107            ErrorKind::InvalidAudience => None,
108            ErrorKind::InvalidSubject => None,
109            ErrorKind::ImmatureSignature => None,
110            ErrorKind::InvalidAlgorithm => None,
111            ErrorKind::UnsupportedAlgorithm => None,
112            ErrorKind::InvalidAlgorithmName => None,
113            ErrorKind::InvalidKeyFormat => None,
114            ErrorKind::Base64(err) => Some(err),
115            ErrorKind::Json(err) => Some(err.as_ref()),
116            ErrorKind::Utf8(err) => Some(err),
117            ErrorKind::Provider(_) => None,
118        }
119    }
120}
121
122impl fmt::Display for Error {
123    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124        match &*self.0 {
125            ErrorKind::InvalidToken
126            | ErrorKind::InvalidSignature
127            | ErrorKind::InvalidEcdsaKey
128            | ErrorKind::ExpiredSignature
129            | ErrorKind::RsaFailedSigning
130            | ErrorKind::MissingAlgorithm
131            | ErrorKind::InvalidIssuer
132            | ErrorKind::InvalidAudience
133            | ErrorKind::InvalidSubject
134            | ErrorKind::ImmatureSignature
135            | ErrorKind::InvalidAlgorithm
136            | ErrorKind::UnsupportedAlgorithm
137            | ErrorKind::InvalidKeyFormat
138            | ErrorKind::InvalidEddsaKey
139            | ErrorKind::InvalidAlgorithmName => write!(f, "{:?}", self.0),
140            ErrorKind::MissingRequiredClaim(c) => write!(f, "Missing required claim: {}", c),
141            ErrorKind::InvalidClaimFormat(c) => write!(f, "Invalid format for claim: {}", c),
142            ErrorKind::InvalidRsaKey(msg) => write!(f, "RSA key invalid: {}", msg),
143            ErrorKind::Signing(msg) => write!(f, "Signing failed: {}", msg),
144            ErrorKind::Json(err) => write!(f, "JSON error: {}", err),
145            ErrorKind::Utf8(err) => write!(f, "UTF-8 error: {}", err),
146            ErrorKind::Base64(err) => write!(f, "Base64 error: {}", err),
147            ErrorKind::Provider(msg) => write!(f, "Custom provider error: {}", msg),
148        }
149    }
150}
151
152impl PartialEq for ErrorKind {
153    fn eq(&self, other: &Self) -> bool {
154        format!("{:?}", self) == format!("{:?}", other)
155    }
156}
157
158// Equality of ErrorKind is an equivalence relation: it is reflexive, symmetric and transitive.
159impl Eq for ErrorKind {}
160
161impl From<base64::DecodeError> for Error {
162    fn from(err: base64::DecodeError) -> Error {
163        new_error(ErrorKind::Base64(err))
164    }
165}
166
167impl From<serde_json::Error> for Error {
168    fn from(err: serde_json::Error) -> Error {
169        new_error(ErrorKind::Json(Arc::new(err)))
170    }
171}
172
173impl From<::std::string::FromUtf8Error> for Error {
174    fn from(err: ::std::string::FromUtf8Error) -> Error {
175        new_error(ErrorKind::Utf8(err))
176    }
177}
178
179impl From<ErrorKind> for Error {
180    fn from(kind: ErrorKind) -> Error {
181        new_error(kind)
182    }
183}
184
185impl From<signature::Error> for Error {
186    fn from(err: signature::Error) -> Error {
187        new_error(ErrorKind::Signing(err.to_string()))
188    }
189}
190
191#[cfg(test)]
192mod tests {
193    use wasm_bindgen_test::wasm_bindgen_test;
194
195    use super::*;
196
197    #[test]
198    #[wasm_bindgen_test]
199    fn test_error_rendering() {
200        assert_eq!(
201            "InvalidAlgorithmName",
202            Error::from(ErrorKind::InvalidAlgorithmName).to_string()
203        );
204    }
205}