Skip to content
Clone
a06673b
50 lines 1.7 KB Rust
use std::sync::Arc;
use axum::extract::{Request, State};
use axum::middleware::Next;
use axum::response::Response;
use rate_limit::AccessTokenBlacklist;
use crate::handlers::JwtState;
/// Services that own a [`JwtState`] can be passed to [`inject_jwt_ctx`], making
/// `AuthUser`/`AuthOptional`/`AuthAdmin` extractors work in their handlers.
pub trait HasJwtState {
fn jwt_state(&self) -> &JwtState;
/// Optional access-token deny-list. When present, the JWT extractors
/// reject any token whose `jti` or user has been revoked (logout,
/// password change, suspension). Defaults to `None` (no deny-check).
fn access_blacklist(&self) -> Option<Arc<AccessTokenBlacklist>> {
None
}
}
/// Middleware that injects the three pieces of context the JWT extractors
/// require from `req.extensions_mut()`:
///
/// 1. `Arc<tokio::sync::RwLock<SigningKeyCache>>` — signing key cache,
/// 2. `JwtSettings` — token validation parameters,
/// 3. `DatabaseConnection` — used to look up sessions during rotation.
///
/// When the service implements [`HasJwtState::access_blacklist`], an
/// `Option<Arc<AccessTokenBlacklist>>` extension is injected as well.
///
/// Apply to any router or route whose handlers depend on
/// `jwt::extractor::{AuthUser, AuthOptional, AuthAdmin}`.
pub async fn inject_jwt_ctx<S>(
State(svc): State<S>,
mut req: Request,
next: Next,
) -> Response
where
S: HasJwtState + Send + Sync + Clone + 'static,
{
let jwt = svc.jwt_state();
req.extensions_mut().insert(jwt.cache.clone());
req.extensions_mut().insert(jwt.settings.clone());
req.extensions_mut().insert(jwt.db.clone());
req.extensions_mut().insert(svc.access_blacklist());
next.run(req).await
}