Closed gbaranski closed 3 years ago
I can see Serialize if you want to log it to json logs but Deserialize?
I can see Serialize if you want to log it to json logs but Deserialize?
yes, deserialize the error returned by the server to allow making some specific action for each token error variant.
nevermind, I'll just implement my own custom error with Serialize/Deserialize trait implemented.
#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
#[serde(tag = "kind", content = "message")]
pub enum Error {
/// When a token doesn't have a valid JWT shape
InvalidToken,
/// When the signature doesn't match
InvalidSignature,
/// When the secret given is not a valid ECDSA key
InvalidEcdsaKey,
/// When the secret given is not a valid RSA key
InvalidRsaKey,
/// When the algorithm from string doesn't match the one passed to `from_str`
InvalidAlgorithmName,
/// When a key is provided with an invalid format
InvalidKeyFormat,
// Validation errors
/// When a token’s `exp` claim indicates that it has expired
ExpiredSignature,
/// When a token’s `iss` claim does not match the expected issuer
InvalidIssuer,
/// When a token’s `aud` claim does not match one of the expected audience values
InvalidAudience,
/// When a token’s `aud` claim does not match one of the expected audience values
InvalidSubject,
/// When a token’s nbf claim represents a time in the future
ImmatureSignature,
/// When the algorithm in the header doesn't match the one passed to `decode` or the encoding/decoding key
/// used doesn't match the alg requested
InvalidAlgorithm,
// 3rd party errors
/// An error happened when decoding some base64 text
Base64(String),
/// An error happened while serializing/deserializing JSON
Json(String),
/// Some of the text was invalid UTF-8
Utf8(String),
/// Something unspecified went wrong with crypto
Crypto(String),
Other,
}
impl From<jsonwebtoken::errors::ErrorKind> for Error {
fn from(val: jsonwebtoken::errors::ErrorKind) -> Self {
use jsonwebtoken::errors::ErrorKind as JWTErrorKind;
match val {
JWTErrorKind::InvalidToken => Self::InvalidToken,
JWTErrorKind::InvalidSignature => Self::InvalidSignature,
JWTErrorKind::InvalidEcdsaKey => Self::InvalidEcdsaKey,
JWTErrorKind::InvalidRsaKey => Self::InvalidRsaKey,
JWTErrorKind::InvalidAlgorithmName => Self::InvalidAlgorithmName,
JWTErrorKind::InvalidKeyFormat => Self::InvalidKeyFormat,
JWTErrorKind::ExpiredSignature => Self::ExpiredSignature,
JWTErrorKind::InvalidIssuer => Self::InvalidIssuer,
JWTErrorKind::InvalidAudience => Self::InvalidAudience,
JWTErrorKind::InvalidSubject => Self::InvalidSubject,
JWTErrorKind::ImmatureSignature => Self::ImmatureSignature,
JWTErrorKind::InvalidAlgorithm => Self::InvalidAlgorithm,
JWTErrorKind::Base64(err) => Self::Base64(err.to_string()),
JWTErrorKind::Json(err) => Self::Json(err.to_string()),
JWTErrorKind::Utf8(err) => Self::Utf8(err.to_string()),
JWTErrorKind::Crypto(err) => Self::Crypto(err.to_string()),
JWTErrorKind::__Nonexhaustive => unreachable!(),
}
}
}
impl From<jsonwebtoken::errors::Error> for Error {
fn from(val: jsonwebtoken::errors::Error) -> Self {
val.into_kind().into()
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
Self::InvalidToken
| Self::InvalidSignature
| Self::InvalidEcdsaKey
| Self::InvalidRsaKey
| Self::ExpiredSignature
| Self::InvalidIssuer
| Self::InvalidAudience
| Self::InvalidSubject
| Self::ImmatureSignature
| Self::InvalidAlgorithm
| Self::InvalidKeyFormat
| Self::InvalidAlgorithmName => write!(f, "{:?}", self),
Self::Json(ref err) => write!(f, "JSON error: {}", err),
Self::Utf8(ref err) => write!(f, "UTF-8 error: {}", err),
Self::Crypto(ref err) => write!(f, "Crypto error: {}", err),
Self::Base64(ref err) => write!(f, "Base64 error: {}", err),
Self::Other => write!(f, "Unknown error"),
}
}
}
#[cfg(feature = "actix")]
impl Error {
fn status_code(&self) -> actix_web::http::StatusCode {
use actix_web::http::StatusCode;
use Error::*;
match self {
InvalidToken | InvalidSignature | ExpiredSignature | InvalidSubject | InvalidIssuer
| InvalidAudience | ImmatureSignature | InvalidAlgorithm | Base64(_) | Json(_)
| Utf8(_) | Crypto(_) | Other => StatusCode::UNAUTHORIZED,
InvalidKeyFormat | InvalidEcdsaKey | InvalidRsaKey | InvalidAlgorithmName => {
StatusCode::INTERNAL_SERVER_ERROR
}
}
}
}
hi, what do you think about that?