diff --git a/api/src/models/error.rs b/api/src/models/error.rs index 64a1dd9..4b8293c 100644 --- a/api/src/models/error.rs +++ b/api/src/models/error.rs @@ -33,6 +33,10 @@ impl AppError { Self::new(ErrorKind::DuplicateRecord(message.to_owned())) } + pub fn expired_token() -> Self { + Self::new(ErrorKind::ExpiredToken) + } + pub fn invalid_password() -> Self { Self::new(ErrorKind::InvalidPassword) } @@ -121,6 +125,7 @@ impl Display for AppError { ErrorKind::DuplicateRecord(message) => { write!(f, "Duplicate database record: {message}") } + ErrorKind::ExpiredToken => write!(f, "The provided token has expired"), ErrorKind::InvalidPassword => write!(f, "Invalid password"), ErrorKind::InvalidToken => write!(f, "The provided token is invalid"), ErrorKind::MissingEnvironmentVariables(missing_vars) => write!( @@ -151,6 +156,7 @@ enum ErrorKind { Database, DbMigration(MigrateError), DuplicateRecord(String), + ExpiredToken, InvalidPassword, InvalidToken, MissingEnvironmentVariables(Vec<&'static str>), @@ -171,7 +177,7 @@ impl IntoResponse for AppError { StatusCode::BAD_REQUEST, ApiResponse::new_with_error(self).into_json_response(), ), - &ErrorKind::NoSessionFound => ( + &ErrorKind::ExpiredToken | &ErrorKind::NoSessionFound => ( StatusCode::UNAUTHORIZED, ApiResponse::new_with_error(self).into_json_response(), ), diff --git a/api/src/services/auth_token.rs b/api/src/services/auth_token.rs index 4c7a197..a14e582 100644 --- a/api/src/services/auth_token.rs +++ b/api/src/services/auth_token.rs @@ -2,11 +2,13 @@ use std::time::{Duration, SystemTime}; use pasetors::{ claims::{Claims, ClaimsValidationRules}, + errors::{ClaimValidationError, Error as TokenError}, footer::Footer, keys::SymmetricKey, local, token::{TrustedToken, UntrustedToken}, version4::V4, + Local, }; use tracing::error; use uuid::Uuid; @@ -22,9 +24,7 @@ pub fn verify_token( token: &str, validation_rules: Option, ) -> Result { - let token = UntrustedToken::try_from(token) - .inspect_err(|err| error!(?err)) - .map_err(|_| AppError::invalid_token())?; + let token = parse_untrusted_token(token)?; let validation_rules = if let Some(validation_rules) = validation_rules { validation_rules @@ -46,10 +46,7 @@ pub fn verify_token( Some("TODO_ENV_NAME_HERE".as_bytes()), ) .inspect_err(|err| error!(?err)) - .map_err(|err| { - error!(?err); - AppError::invalid_token() - })?; + .map_err(map_token_error)?; Ok(token) } @@ -118,6 +115,22 @@ fn generate_token( (token, token_id, now + expires_in) } +fn parse_untrusted_token(token: &str) -> Result, AppError> { + UntrustedToken::try_from(token) + .inspect_err(|err| error!(?err)) + .map_err(map_token_error) +} + +fn map_token_error(err: TokenError) -> AppError { + match err { + TokenError::ClaimValidation(claim_validation_error) => match claim_validation_error { + ClaimValidationError::Exp => AppError::expired_token(), + _ => AppError::invalid_token(), + }, + _ => AppError::invalid_token(), + } +} + #[cfg(test)] mod tests { use base64::prelude::*;