Return the proper error if trying to verify an expired token

This commit is contained in:
Z. Charles Dziura 2024-10-05 13:39:16 -04:00
parent 3768cd26e6
commit 680114f467
2 changed files with 27 additions and 8 deletions

View file

@ -33,6 +33,10 @@ impl AppError {
Self::new(ErrorKind::DuplicateRecord(message.to_owned())) Self::new(ErrorKind::DuplicateRecord(message.to_owned()))
} }
pub fn expired_token() -> Self {
Self::new(ErrorKind::ExpiredToken)
}
pub fn invalid_password() -> Self { pub fn invalid_password() -> Self {
Self::new(ErrorKind::InvalidPassword) Self::new(ErrorKind::InvalidPassword)
} }
@ -121,6 +125,7 @@ impl Display for AppError {
ErrorKind::DuplicateRecord(message) => { ErrorKind::DuplicateRecord(message) => {
write!(f, "Duplicate database record: {message}") write!(f, "Duplicate database record: {message}")
} }
ErrorKind::ExpiredToken => write!(f, "The provided token has expired"),
ErrorKind::InvalidPassword => write!(f, "Invalid password"), ErrorKind::InvalidPassword => write!(f, "Invalid password"),
ErrorKind::InvalidToken => write!(f, "The provided token is invalid"), ErrorKind::InvalidToken => write!(f, "The provided token is invalid"),
ErrorKind::MissingEnvironmentVariables(missing_vars) => write!( ErrorKind::MissingEnvironmentVariables(missing_vars) => write!(
@ -151,6 +156,7 @@ enum ErrorKind {
Database, Database,
DbMigration(MigrateError), DbMigration(MigrateError),
DuplicateRecord(String), DuplicateRecord(String),
ExpiredToken,
InvalidPassword, InvalidPassword,
InvalidToken, InvalidToken,
MissingEnvironmentVariables(Vec<&'static str>), MissingEnvironmentVariables(Vec<&'static str>),
@ -171,7 +177,7 @@ impl IntoResponse for AppError {
StatusCode::BAD_REQUEST, StatusCode::BAD_REQUEST,
ApiResponse::new_with_error(self).into_json_response(), ApiResponse::new_with_error(self).into_json_response(),
), ),
&ErrorKind::NoSessionFound => ( &ErrorKind::ExpiredToken | &ErrorKind::NoSessionFound => (
StatusCode::UNAUTHORIZED, StatusCode::UNAUTHORIZED,
ApiResponse::new_with_error(self).into_json_response(), ApiResponse::new_with_error(self).into_json_response(),
), ),

View file

@ -2,11 +2,13 @@ use std::time::{Duration, SystemTime};
use pasetors::{ use pasetors::{
claims::{Claims, ClaimsValidationRules}, claims::{Claims, ClaimsValidationRules},
errors::{ClaimValidationError, Error as TokenError},
footer::Footer, footer::Footer,
keys::SymmetricKey, keys::SymmetricKey,
local, local,
token::{TrustedToken, UntrustedToken}, token::{TrustedToken, UntrustedToken},
version4::V4, version4::V4,
Local,
}; };
use tracing::error; use tracing::error;
use uuid::Uuid; use uuid::Uuid;
@ -22,9 +24,7 @@ pub fn verify_token(
token: &str, token: &str,
validation_rules: Option<ClaimsValidationRules>, validation_rules: Option<ClaimsValidationRules>,
) -> Result<TrustedToken, AppError> { ) -> Result<TrustedToken, AppError> {
let token = UntrustedToken::try_from(token) let token = parse_untrusted_token(token)?;
.inspect_err(|err| error!(?err))
.map_err(|_| AppError::invalid_token())?;
let validation_rules = if let Some(validation_rules) = validation_rules { let validation_rules = if let Some(validation_rules) = validation_rules {
validation_rules validation_rules
@ -46,10 +46,7 @@ pub fn verify_token(
Some("TODO_ENV_NAME_HERE".as_bytes()), Some("TODO_ENV_NAME_HERE".as_bytes()),
) )
.inspect_err(|err| error!(?err)) .inspect_err(|err| error!(?err))
.map_err(|err| { .map_err(map_token_error)?;
error!(?err);
AppError::invalid_token()
})?;
Ok(token) Ok(token)
} }
@ -118,6 +115,22 @@ fn generate_token(
(token, token_id, now + expires_in) (token, token_id, now + expires_in)
} }
fn parse_untrusted_token(token: &str) -> Result<UntrustedToken<Local, V4>, 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)] #[cfg(test)]
mod tests { mod tests {
use base64::prelude::*; use base64::prelude::*;