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