From 577fd4078b6e3b0c82e3a1521f1c4d1e233c816e Mon Sep 17 00:00:00 2001 From: Nico Fricke Date: Mon, 20 Jan 2025 15:30:35 +0100 Subject: [PATCH] first prototype for simple authorization middleware --- casket-backend/src/auth.rs | 41 +++++++++++++++++++++------ casket-bruno-collection/Auth.bru | 28 ++++++++++++++++++ casket-bruno-collection/Get Files.bru | 14 ++++++++- casket-bruno-collection/Invalid.bru | 11 +++++++ 4 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 casket-bruno-collection/Auth.bru create mode 100644 casket-bruno-collection/Invalid.bru diff --git a/casket-backend/src/auth.rs b/casket-backend/src/auth.rs index 878a975..325f614 100644 --- a/casket-backend/src/auth.rs +++ b/casket-backend/src/auth.rs @@ -1,16 +1,19 @@ -use axum::extract::{FromRef, Request, State}; +use crate::AppState; +use axum::extract::{FromRef, Path, Request, State}; use axum::http::StatusCode; use axum::middleware::Next; use axum::response::{IntoResponse, Response}; -use axum_extra::headers::Authorization; use axum_extra::headers::authorization::Bearer; +use axum_extra::headers::Authorization; use axum_extra::TypedHeader; use axum_jwks::Jwks; use serde::{Deserialize, Serialize}; -use crate::AppState; +use tracing::debug; #[derive(Deserialize, Serialize)] -struct Claims {} +struct Claims { + sub: String, +} impl FromRef for Jwks { fn from_ref(state: &AppState) -> Self { @@ -20,15 +23,35 @@ impl FromRef for Jwks { pub async fn validate_token( State(state): State, - TypedHeader(Authorization(bearer)): TypedHeader>, + user: Option>, + auth_header: Option>>, request: Request, next: Next, ) -> Response { let jwks = Jwks::from_ref(&state); - - if jwks.validate_claims::(bearer.token()).is_err() { - return StatusCode::UNAUTHORIZED.into_response(); + if request.uri().path().starts_with("/api/v1/user/") { + if auth_header.is_none() { + debug!("No auth header passed."); + return StatusCode::UNAUTHORIZED.into_response(); + } + match jwks.validate_claims::(auth_header.unwrap().0 .0.token()) { + Err(err) => { + debug!("JWT validation failed: {:?}", err); + return StatusCode::UNAUTHORIZED.into_response(); + } + Ok(jwk) => match user { + Some(user) => { + if !user.0.eq(&jwk.claims.sub) { + debug!("JWT sub {:?} does not match user {:?}", jwk.claims.sub, user.0); + return StatusCode::FORBIDDEN.into_response(); + } + } + None => { + panic!("User was none") + } + }, + } } next.run(request).await -} \ No newline at end of file +} diff --git a/casket-bruno-collection/Auth.bru b/casket-bruno-collection/Auth.bru new file mode 100644 index 0000000..b0ff98c --- /dev/null +++ b/casket-bruno-collection/Auth.bru @@ -0,0 +1,28 @@ +meta { + name: Auth + type: http + seq: 5 +} + +get { + url: http://localhost:3000/api/v1/user/test123/files?path=&nesting=5 + body: none + auth: oauth2 +} + +params:query { + path: + nesting: 5 +} + +auth:oauth2 { + grant_type: authorization_code + callback_url: https://localhost:1234 + authorization_url: https://login.nifni.net/realms/public_selfhosted/protocol/openid-connect/auth + access_token_url: https://login.nifni.net/realms/public_selfhosted/protocol/openid-connect/token + client_id: casket + client_secret: + scope: + state: + pkce: false +} diff --git a/casket-bruno-collection/Get Files.bru b/casket-bruno-collection/Get Files.bru index 385efda..43ad9f5 100644 --- a/casket-bruno-collection/Get Files.bru +++ b/casket-bruno-collection/Get Files.bru @@ -7,10 +7,22 @@ meta { get { url: http://localhost:3000/api/v1/user/test123/files?path=&nesting=5 body: none - auth: none + auth: oauth2 } params:query { path: nesting: 5 } + +auth:oauth2 { + grant_type: authorization_code + callback_url: https://localhost:1234 + authorization_url: https://login.nifni.net/realms/public_selfhosted/protocol/openid-connect/auth + access_token_url: https://login.nifni.net/realms/public_selfhosted/protocol/openid-connect/token + client_id: casket + client_secret: + scope: + state: + pkce: false +} diff --git a/casket-bruno-collection/Invalid.bru b/casket-bruno-collection/Invalid.bru new file mode 100644 index 0000000..23c1fab --- /dev/null +++ b/casket-bruno-collection/Invalid.bru @@ -0,0 +1,11 @@ +meta { + name: Invalid + type: http + seq: 6 +} + +get { + url: http://localhost:3000/api/v1/user/ + body: none + auth: none +}