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