diff --git a/Cargo.toml b/Cargo.toml index 30a8a14..5193a46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,11 +19,10 @@ tower_governor = "0.8.0" hex = "0.4" jwt-compact = { version = "0.8.0", features = ["es256k"] } scrypt = "0.11" -#lettre = { version = "0.11.18", default-features = false, features = ["pool", "tokio1-rustls", "smtp-transport", "hostname", "builder"] } -#lettre = { version = "0.11", default-features = false, features = ["builder", "webpki-roots", "rustls", "aws-lc-rs", "smtp-transport", "tokio1", "tokio1-rustls"] } +#Leaveing these two cause I think it is needed by the aws-lc-rs = "1.13.0" -lettre = { version = "0.11", default-features = false, features = ["builder", "webpki-roots", "rustls", "aws-lc-rs", "smtp-transport", "tokio1", "tokio1-rustls"] } rustls = { version = "0.23", default-features = false, features = ["tls12", "std", "logging", "aws_lc_rs"] } +lettre = { version = "0.11", default-features = false, features = ["builder", "webpki-roots", "rustls", "aws-lc-rs", "smtp-transport", "tokio1", "tokio1-rustls"] } handlebars = { version = "6.3.2", features = ["rust-embed"] } rust-embed = "8.7.2" axum-template = { version = "3.0.0", features = ["handlebars"] } diff --git a/src/main.rs b/src/main.rs index 03bb851..abf3306 100644 --- a/src/main.rs +++ b/src/main.rs @@ -175,6 +175,9 @@ async fn main() -> Result<(), Box> { .finish() .expect("failed to create governor config. this should not happen and is a bug"); + // let create_account_limiter_time: Option = + // env::var("GATEKEEPER_CREATE_ACCOUNT_LIMITER_WINDOW").unwrap_or_else(|_| None); + let create_session_governor_limiter = create_session_governor_conf.limiter().clone(); let sign_in_governor_limiter = sign_in_governor_conf.limiter().clone(); let interval = Duration::from_secs(60); diff --git a/src/middleware.rs b/src/middleware.rs index ef9c104..3025c38 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -1,5 +1,6 @@ use crate::helpers::json_error_response; use axum::extract::Request; +use axum::http::header::AUTHORIZATION; use axum::http::{HeaderMap, StatusCode}; use axum::middleware::Next; use axum::response::IntoResponse; @@ -12,21 +13,31 @@ use tracing::log; #[derive(Clone, Debug)] pub struct Did(pub Option); +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum AuthScheme { + Bearer, + DPoP, +} + #[derive(Serialize, Deserialize)] pub struct TokenClaims { pub sub: String, } pub async fn extract_did(mut req: Request, next: Next) -> impl IntoResponse { - let token = extract_bearer(req.headers()); + let auth = extract_auth(req.headers()); - match token { - Ok(token) => { - match token { + match auth { + Ok(auth_opt) => { + match auth_opt { None => json_error_response(StatusCode::BAD_REQUEST, "TokenRequired", "") .expect("Error creating an error response"), - Some(token) => { - let token = UntrustedToken::new(&token); + Some((scheme, token_str)) => { + // For Bearer, validate JWT and extract DID from `sub`. + // For DPoP, we currently only pass through and do not validate here; insert None DID. + // match scheme { + // AuthScheme::Bearer => { + let token = UntrustedToken::new(&token_str); if token.is_err() { return json_error_response(StatusCode::BAD_REQUEST, "TokenRequired", "") .expect("Error creating an error response"); @@ -49,9 +60,16 @@ pub async fn extract_did(mut req: Request, next: Next) -> impl IntoResponse { .expect("Error creating an error response"); } let token = token.expect("Already checked for error,"); - //Not going to worry about expiration since it still goes to the PDS + // Not going to worry about expiration since it still goes to the PDS req.extensions_mut() .insert(Did(Some(token.claims().custom.sub.clone()))); + // } + // AuthScheme::DPoP => { + // // No DID extraction from DPoP here; leave None + // req.extensions_mut().insert(Did(None)); + // } + // } + next.run(req).await } } @@ -64,19 +82,24 @@ pub async fn extract_did(mut req: Request, next: Next) -> impl IntoResponse { } } -fn extract_bearer(headers: &HeaderMap) -> Result, String> { +fn extract_auth(headers: &HeaderMap) -> Result, String> { match headers.get(axum::http::header::AUTHORIZATION) { None => Ok(None), - Some(hv) => match hv.to_str() { - Err(_) => Err("Authorization header is not valid".into()), - Ok(s) => { - // Accept forms like: "Bearer " (case-sensitive for the scheme here) - let mut parts = s.splitn(2, ' '); - match (parts.next(), parts.next()) { - (Some("Bearer"), Some(tok)) if !tok.is_empty() => Ok(Some(tok.to_string())), - _ => Err("Authorization header must be in format 'Bearer '".into()), + Some(hv) => { + match hv.to_str() { + Err(_) => Err("Authorization header is not valid".into()), + Ok(s) => { + // Accept forms like: "Bearer " or "DPoP " (case-sensitive for the scheme here) + let mut parts = s.splitn(2, ' '); + match (parts.next(), parts.next()) { + (Some("Bearer"), Some(tok)) if !tok.is_empty() => + Ok(Some((AuthScheme::Bearer, tok.to_string()))), + (Some("DPoP"), Some(tok)) if !tok.is_empty() => + Ok(Some((AuthScheme::DPoP, tok.to_string()))), + _ => Err("Authorization header must be in format 'Bearer ' or 'DPoP '".into()), + } } } - }, + } } }