jsonwebtoken/
errors.rs

1use std::error::Error as StdError;
2use std::fmt;
3use std::result;
4
5/// A crate private constructor for `Error`.
6pub(crate) fn new_error(kind: ErrorKind) -> Error {
7    Error(Box::new(kind))
8}
9
10/// A type alias for `Result<T, jsonwebtoken::Error>`.
11pub type Result<T> = result::Result<T, Error>;
12
13/// An error that can occur when encoding/decoding JWTs
14#[derive(Debug)]
15pub struct Error(Box<ErrorKind>);
16
17impl Error {
18    /// Return the specific type of this error.
19    pub fn kind(&self) -> &ErrorKind {
20        &self.0
21    }
22
23    /// Unwrap this error into its underlying type.
24    pub fn into_kind(self) -> ErrorKind {
25        *self.0
26    }
27}
28
29/// The specific type of an error.
30#[derive(Debug)]
31pub enum ErrorKind {
32    /// When a token doesn't have a valid JWT shape
33    InvalidToken,
34    /// When the signature doesn't match
35    InvalidSignature,
36    /// When the secret given is not a valid ECDSA key
37    InvalidEcdsaKey,
38    /// When the secret given is not a valid RSA key
39    InvalidRsaKey,
40    /// When the algorithm from string doesn't match the one passed to `from_str`
41    InvalidAlgorithmName,
42    /// When a key is provided with an invalid format
43    InvalidKeyFormat,
44
45    // Validation errors
46    /// When a token’s `exp` claim indicates that it has expired
47    ExpiredSignature,
48    /// When a token’s `iss` claim does not match the expected issuer
49    InvalidIssuer,
50    /// When a token’s `aud` claim does not match one of the expected audience values
51    InvalidAudience,
52    /// When a token’s `aud` claim does not match one of the expected audience values
53    InvalidSubject,
54    /// When a token’s nbf claim represents a time in the future
55    ImmatureSignature,
56    /// When the algorithm in the header doesn't match the one passed to `decode` or the encoding/decoding key
57    /// used doesn't match the alg requested
58    InvalidAlgorithm,
59
60    // 3rd party errors
61    /// An error happened when decoding some base64 text
62    Base64(base64::DecodeError),
63    /// An error happened while serializing/deserializing JSON
64    Json(serde_json::Error),
65    /// Some of the text was invalid UTF-8
66    Utf8(::std::string::FromUtf8Error),
67    /// Something unspecified went wrong with crypto
68    Crypto(::ring::error::Unspecified),
69
70    /// Hints that destructuring should not be exhaustive.
71    ///
72    /// This enum may grow additional variants, so this makes sure clients
73    /// don't count on exhaustive matching. (Otherwise, adding a new variant
74    /// could break existing code.)
75    #[doc(hidden)]
76    __Nonexhaustive,
77}
78
79impl StdError for Error {
80    fn cause(&self) -> Option<&dyn StdError> {
81        match *self.0 {
82            ErrorKind::InvalidToken => None,
83            ErrorKind::InvalidSignature => None,
84            ErrorKind::InvalidEcdsaKey => None,
85            ErrorKind::InvalidRsaKey => None,
86            ErrorKind::ExpiredSignature => None,
87            ErrorKind::InvalidIssuer => None,
88            ErrorKind::InvalidAudience => None,
89            ErrorKind::InvalidSubject => None,
90            ErrorKind::ImmatureSignature => None,
91            ErrorKind::InvalidAlgorithm => None,
92            ErrorKind::InvalidAlgorithmName => None,
93            ErrorKind::InvalidKeyFormat => None,
94            ErrorKind::Base64(ref err) => Some(err),
95            ErrorKind::Json(ref err) => Some(err),
96            ErrorKind::Utf8(ref err) => Some(err),
97            ErrorKind::Crypto(ref err) => Some(err),
98            ErrorKind::__Nonexhaustive => None,
99        }
100    }
101}
102
103impl fmt::Display for Error {
104    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105        match *self.0 {
106            ErrorKind::InvalidToken
107            | ErrorKind::InvalidSignature
108            | ErrorKind::InvalidEcdsaKey
109            | ErrorKind::InvalidRsaKey
110            | ErrorKind::ExpiredSignature
111            | ErrorKind::InvalidIssuer
112            | ErrorKind::InvalidAudience
113            | ErrorKind::InvalidSubject
114            | ErrorKind::ImmatureSignature
115            | ErrorKind::InvalidAlgorithm
116            | ErrorKind::InvalidKeyFormat
117            | ErrorKind::InvalidAlgorithmName => write!(f, "{:?}", self.0),
118            ErrorKind::Json(ref err) => write!(f, "JSON error: {}", err),
119            ErrorKind::Utf8(ref err) => write!(f, "UTF-8 error: {}", err),
120            ErrorKind::Crypto(ref err) => write!(f, "Crypto error: {}", err),
121            ErrorKind::Base64(ref err) => write!(f, "Base64 error: {}", err),
122            ErrorKind::__Nonexhaustive => write!(f, "Unknown error"),
123        }
124    }
125}
126
127impl From<base64::DecodeError> for Error {
128    fn from(err: base64::DecodeError) -> Error {
129        new_error(ErrorKind::Base64(err))
130    }
131}
132
133impl From<serde_json::Error> for Error {
134    fn from(err: serde_json::Error) -> Error {
135        new_error(ErrorKind::Json(err))
136    }
137}
138
139impl From<::std::string::FromUtf8Error> for Error {
140    fn from(err: ::std::string::FromUtf8Error) -> Error {
141        new_error(ErrorKind::Utf8(err))
142    }
143}
144
145impl From<::ring::error::Unspecified> for Error {
146    fn from(err: ::ring::error::Unspecified) -> Error {
147        new_error(ErrorKind::Crypto(err))
148    }
149}
150
151impl From<::ring::error::KeyRejected> for Error {
152    fn from(_err: ::ring::error::KeyRejected) -> Error {
153        new_error(ErrorKind::InvalidEcdsaKey)
154    }
155}
156
157impl From<ErrorKind> for Error {
158    fn from(kind: ErrorKind) -> Error {
159        new_error(kind)
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166
167    #[test]
168    fn test_error_rendering() {
169        assert_eq!(
170            "InvalidAlgorithmName",
171            Error::from(ErrorKind::InvalidAlgorithmName).to_string()
172        );
173    }
174}