Skip to content
Clone
e1df092
91 lines 2.6 KB Rust
use std::sync::Arc;
use axum::Extension;
use axum::extract::{Request, State};
use axum::http::StatusCode;
use axum::middleware::Next;
use axum::response::{IntoResponse, Response};
use export::AppState;
use crate::oauth::{append_cookie, read_cookie_header};
const SKIP_PREFIXES: [&str; 8] = [
"/healthz",
"/readyz",
"/api/docs",
"/api/v1/auth/",
"/api/v1/internal",
"/assets",
"/pages",
"/swagger",
];
pub async fn revalidate(
State(state): State<AppState>,
Extension(verifier): Extension<Arc<jwt::JwtVerifier>>,
request: Request,
next: Next,
) -> Response {
let path = request.uri().path();
if SKIP_PREFIXES.iter().any(|prefix| path.starts_with(prefix)) {
return next.run(request).await;
}
let Some(token) = read_cookie_header(request.headers(), &state.config.oauth.session_cookie)
.map(str::to_owned)
else {
return next.run(request).await;
};
let Ok(claims) = verifier.verify_access(&token).await else {
return next.run(request).await;
};
let Some(session_id) = claims.sid.as_deref() else {
return next.run(request).await;
};
let Some(kenauth) = state.kenauth.as_ref() else {
return next.run(request).await;
};
let key = format!("oauth:recheck:{}:{}", session_id, claims.security_version);
if export::redis::get_string(&state.redis, &key)
.await
.ok()
.flatten()
.is_some()
{
return next.run(request).await;
}
match kenauth
.get_session(claims.sub, claims.security_version, session_id)
.await
{
Ok(_) => {
let _ =
export::redis::set_string(&state.redis, &key, "1", state.config.oauth.recheck_secs)
.await;
next.run(request).await
}
Err(kenauth::KenAuthError::Unauthenticated) | Err(kenauth::KenAuthError::NotFound) => {
let mut response = (
StatusCode::UNAUTHORIZED,
axum::Json(serde_json::json!({
"code": 401,
"message": "session_revoked",
"data": null,
"error": null,
"error_code": "session_revoked",
"request_id": null,
"log_id": null,
})),
)
.into_response();
append_cookie(
&mut response,
&jwt::clear_session_cookie(&state.config.oauth),
);
response
}
Err(_) => next.run(request).await,
}
}