1 use std::error::Error as StdError;
2 use std::fmt;
3 use std::result;
4 
5 /// A crate private constructor for `Error`.
new_error(kind: ErrorKind) -> Error6 pub(crate) fn new_error(kind: ErrorKind) -> Error {
7     Error(Box::new(kind))
8 }
9 
10 /// A type alias for `Result<T, jsonwebtoken::Error>`.
11 pub type Result<T> = result::Result<T, Error>;
12 
13 /// An error that can occur when encoding/decoding JWTs
14 #[derive(Debug)]
15 pub struct Error(Box<ErrorKind>);
16 
17 impl Error {
18     /// Return the specific type of this error.
kind(&self) -> &ErrorKind19     pub fn kind(&self) -> &ErrorKind {
20         &self.0
21     }
22 
23     /// Unwrap this error into its underlying type.
into_kind(self) -> ErrorKind24     pub fn into_kind(self) -> ErrorKind {
25         *self.0
26     }
27 }
28 
29 /// The specific type of an error.
30 #[derive(Debug)]
31 pub 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 
79 impl StdError for Error {
cause(&self) -> Option<&dyn StdError>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 
103 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result104     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 
127 impl From<base64::DecodeError> for Error {
from(err: base64::DecodeError) -> Error128     fn from(err: base64::DecodeError) -> Error {
129         new_error(ErrorKind::Base64(err))
130     }
131 }
132 
133 impl From<serde_json::Error> for Error {
from(err: serde_json::Error) -> Error134     fn from(err: serde_json::Error) -> Error {
135         new_error(ErrorKind::Json(err))
136     }
137 }
138 
139 impl From<::std::string::FromUtf8Error> for Error {
from(err: ::std::string::FromUtf8Error) -> Error140     fn from(err: ::std::string::FromUtf8Error) -> Error {
141         new_error(ErrorKind::Utf8(err))
142     }
143 }
144 
145 impl From<::ring::error::Unspecified> for Error {
from(err: ::ring::error::Unspecified) -> Error146     fn from(err: ::ring::error::Unspecified) -> Error {
147         new_error(ErrorKind::Crypto(err))
148     }
149 }
150 
151 impl From<::ring::error::KeyRejected> for Error {
from(_err: ::ring::error::KeyRejected) -> Error152     fn from(_err: ::ring::error::KeyRejected) -> Error {
153         new_error(ErrorKind::InvalidEcdsaKey)
154     }
155 }
156 
157 impl From<ErrorKind> for Error {
from(kind: ErrorKind) -> Error158     fn from(kind: ErrorKind) -> Error {
159         new_error(kind)
160     }
161 }
162 
163 #[cfg(test)]
164 mod tests {
165     use super::*;
166 
167     #[test]
test_error_rendering()168     fn test_error_rendering() {
169         assert_eq!(
170             "InvalidAlgorithmName",
171             Error::from(ErrorKind::InvalidAlgorithmName).to_string()
172         );
173     }
174 }
175