From af29f396569b18cc29ecce090217ff64338d44f6 Mon Sep 17 00:00:00 2001 From: cduvray Date: Mon, 16 Jan 2023 23:32:51 +0100 Subject: [PATCH] fix: jwks store unavailable should be error 500 - fix - 403 -> 401 for some errors - errors refactoring --- jwt-authorizer/src/error.rs | 14 ++++++------- jwt-authorizer/src/layer.rs | 41 +++++++++++++++---------------------- jwt-authorizer/src/tests.rs | 4 ++-- 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/jwt-authorizer/src/error.rs b/jwt-authorizer/src/error.rs index b90d2b1..6c0b10b 100644 --- a/jwt-authorizer/src/error.rs +++ b/jwt-authorizer/src/error.rs @@ -1,5 +1,4 @@ use axum::{ - extract::rejection::TypedHeaderRejection, http::StatusCode, response::{IntoResponse, Response}, }; @@ -37,8 +36,8 @@ pub enum AuthError { #[error("Invalid Key Algorithm {0:?}")] InvalidKeyAlg(Algorithm), - #[error(transparent)] - InvalidTokenHeader(#[from] TypedHeaderRejection), + // #[error(transparent)] + // InvalidTokenHeader(#[from] TypedHeaderRejection), #[error(transparent)] InvalidToken(#[from] jsonwebtoken::errors::Error), @@ -49,16 +48,17 @@ pub enum AuthError { impl IntoResponse for AuthError { fn into_response(self) -> Response { + // TODO: add error code (https://datatracker.ietf.org/doc/html/rfc6750#section-3.1) warn!("AuthError: {}", &self); let (status, error_message) = match self { AuthError::JwksRefreshError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), - AuthError::InvalidKid(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg), - AuthError::InvalidTokenHeader(_) => (StatusCode::BAD_REQUEST, self.to_string()), - AuthError::InvalidToken(_) => (StatusCode::BAD_REQUEST, self.to_string()), + AuthError::InvalidKid(msg) => (StatusCode::UNAUTHORIZED, msg), + // AuthError::InvalidTokenHeader(_) => (StatusCode::BAD_REQUEST, self.to_string()), + AuthError::InvalidToken(_) => (StatusCode::UNAUTHORIZED, self.to_string()), AuthError::InvalidKey(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg), AuthError::JwksSerialisationError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), AuthError::InvalidKeyAlg(_) => (StatusCode::BAD_REQUEST, self.to_string()), - AuthError::InvalidClaims() => (StatusCode::FORBIDDEN, self.to_string()), + AuthError::InvalidClaims() => (StatusCode::UNAUTHORIZED, self.to_string()), }; let body = axum::Json(serde_json::json!({ "error": error_message, diff --git a/jwt-authorizer/src/layer.rs b/jwt-authorizer/src/layer.rs index f534e74..2c7b40c 100644 --- a/jwt-authorizer/src/layer.rs +++ b/jwt-authorizer/src/layer.rs @@ -1,6 +1,6 @@ +use axum::body::BoxBody; use axum::http::Request; -use axum::response::IntoResponse; -use axum::{body::Body, response::Response}; +use axum::response::{Response, IntoResponse}; use futures_core::ready; use futures_util::future::BoxFuture; use headers::authorization::Bearer; @@ -123,7 +123,7 @@ where C: Clone + DeserializeOwned + Send + Sync + 'static, { type RequestBody = B; - type ResponseBody = Body; + type ResponseBody = BoxBody; type Future = BoxFuture<'static, Result, Response>>; fn authorize(&self, mut request: Request) -> Self::Future { @@ -132,27 +132,20 @@ where let bearer_o: Option> = h.typed_get(); Box::pin(async move { if let Some(bearer) = bearer_o { - if let Ok(token_data) = authorizer.check_auth(bearer.token()).await { - // Set `token_data` as a request extension so it can be accessed by other - // services down the stack. - request.extensions_mut().insert(token_data); - - Ok(request) - } else { - let unauthorized_response = Response::builder() - .status(StatusCode::UNAUTHORIZED) - .body(Body::empty()) // TODO: add error code (https://datatracker.ietf.org/doc/html/rfc6750#section-3.1) - .unwrap(); - - Err(unauthorized_response) + match authorizer.check_auth(bearer.token()).await { + Ok(token_data) => { + // Set `token_data` as a request extension so it can be accessed by other + // services down the stack. + request.extensions_mut().insert(token_data); + + Ok(request) + }, + Err(err) => { + Err(err.into_response()) + } } } else { - let unauthorized_response = Response::builder() - .status(StatusCode::UNAUTHORIZED) - .body(Body::empty()) // TODO: add error message (https://datatracker.ietf.org/doc/html/rfc6750#section-3.1) - .unwrap(); - - Err(unauthorized_response) + Err((StatusCode::UNAUTHORIZED).into_response()) } }) } @@ -302,9 +295,7 @@ where } Err(res) => { tracing::info!("err: {:?}", res); - let r = (StatusCode::FORBIDDEN, format!("Unauthorized : {:?}", res)).into_response(); - // TODO: replace r by res (type problems: res should be already a 403 error response) - return Poll::Ready(Ok(r)); + return Poll::Ready(Ok(res)); } }; } diff --git a/jwt-authorizer/src/tests.rs b/jwt-authorizer/src/tests.rs index 3df8c83..b77b645 100644 --- a/jwt-authorizer/src/tests.rs +++ b/jwt-authorizer/src/tests.rs @@ -47,7 +47,7 @@ mod tests { .await .unwrap(); - assert_eq!(response.status(), StatusCode::FORBIDDEN); + assert_eq!(response.status(), StatusCode::UNAUTHORIZED); // TODO: check error code (https://datatracker.ietf.org/doc/html/rfc6750#section-3.1) } @@ -73,7 +73,7 @@ mod tests { "xxx.xxx.xxx" ).await; - assert_eq!(response.status(), StatusCode::FORBIDDEN); + assert_eq!(response.status(), StatusCode::UNAUTHORIZED); // TODO: check error code (https://datatracker.ietf.org/doc/html/rfc6750#section-3.1) }