use std::fmt;
use actix_web::HttpResponse;
use actix_web::http::StatusCode;
#[derive(Debug)]
pub enum JwtError {
MissingSecretKey,
Forbidden,
MissingAuthenticator,
MissingLoginValues,
FailedAuthentication,
FailedTokenCreation,
ExpiredToken,
EmptyAuthHeader,
MissingExpField,
WrongFormatOfExp,
InvalidAuthHeader,
EmptyQueryToken,
EmptyCookieToken,
EmptyParamToken,
InvalidSigningAlgorithm,
NoPrivKeyFile,
NoPubKeyFile,
InvalidPrivKey,
InvalidPubKey,
MissingRefreshToken,
InvalidRefreshToken,
RefreshTokenNotFound,
RefreshTokenExpired,
TokenEmpty,
ExpiryInPast,
TokenParsing(String),
TokenExtraction(String),
Internal(String),
}
impl fmt::Display for JwtError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MissingSecretKey => write!(f, "secret key is required"),
Self::Forbidden => {
write!(f, "you don't have permission to access this resource")
}
Self::MissingAuthenticator => write!(f, "authenticator func is undefined"),
Self::MissingLoginValues => write!(f, "missing Username or Password"),
Self::FailedAuthentication => write!(f, "incorrect Username or Password"),
Self::FailedTokenCreation => write!(f, "failed to create JWT Token"),
Self::ExpiredToken => write!(f, "token is expired"),
Self::EmptyAuthHeader => write!(f, "auth header is empty"),
Self::MissingExpField => write!(f, "missing exp field"),
Self::WrongFormatOfExp => write!(f, "exp must be float64 format"),
Self::InvalidAuthHeader => write!(f, "auth header is invalid"),
Self::EmptyQueryToken => write!(f, "query token is empty"),
Self::EmptyCookieToken => write!(f, "cookie token is empty"),
Self::EmptyParamToken => write!(f, "parameter token is empty"),
Self::InvalidSigningAlgorithm => write!(f, "invalid signing algorithm"),
Self::NoPrivKeyFile => write!(f, "private key file unreadable"),
Self::NoPubKeyFile => write!(f, "public key file unreadable"),
Self::InvalidPrivKey => write!(f, "private key invalid"),
Self::InvalidPubKey => write!(f, "public key invalid"),
Self::MissingRefreshToken => write!(f, "missing refresh_token parameter"),
Self::InvalidRefreshToken => write!(f, "invalid or expired refresh token"),
Self::RefreshTokenNotFound => write!(f, "refresh token not found"),
Self::RefreshTokenExpired => write!(f, "refresh token expired"),
Self::TokenEmpty => write!(f, "token cannot be empty"),
Self::ExpiryInPast => write!(f, "token expiry time must be in the future"),
Self::TokenParsing(msg) => write!(f, "{msg}"),
Self::TokenExtraction(msg) => write!(f, "{msg}"),
Self::Internal(msg) => write!(f, "{msg}"),
}
}
}
impl std::error::Error for JwtError {}
impl JwtError {
pub fn is_token_parsing(&self) -> bool {
matches!(self, Self::TokenParsing(_))
}
pub fn is_token_extraction(&self) -> bool {
matches!(self, Self::TokenExtraction(_))
}
pub fn is_forbidden(&self) -> bool {
matches!(self, Self::Forbidden)
}
}
impl actix_web::ResponseError for JwtError {
fn status_code(&self) -> StatusCode {
match self {
Self::Forbidden => StatusCode::FORBIDDEN,
Self::MissingSecretKey
| Self::MissingAuthenticator
| Self::FailedTokenCreation
| Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::MissingLoginValues
| Self::EmptyAuthHeader
| Self::MissingExpField
| Self::WrongFormatOfExp
| Self::InvalidAuthHeader
| Self::EmptyQueryToken
| Self::EmptyCookieToken
| Self::EmptyParamToken
| Self::MissingRefreshToken
| Self::TokenExtraction(_) => StatusCode::BAD_REQUEST,
Self::FailedAuthentication
| Self::ExpiredToken
| Self::InvalidSigningAlgorithm
| Self::NoPrivKeyFile
| Self::NoPubKeyFile
| Self::InvalidPrivKey
| Self::InvalidPubKey
| Self::InvalidRefreshToken
| Self::RefreshTokenNotFound
| Self::RefreshTokenExpired
| Self::TokenEmpty
| Self::ExpiryInPast
| Self::TokenParsing(_) => StatusCode::UNAUTHORIZED,
}
}
fn error_response(&self) -> HttpResponse {
HttpResponse::build(self.status_code()).json(serde_json::json!({
"code": self.status_code().as_u16(),
"message": self.to_string(),
}))
}
}