10890d2
use std::sync::Arc;
use actix_web::body::{BoxBody, MessageBody};
use actix_web::dev::{ServiceRequest, ServiceResponse};
use actix_web::middleware::Next;
use actix_web::web::Data;
use actix_web::{Error, HttpResponse};
use export::AppState;
use crate::auth::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<B>(
request: ServiceRequest,
next: Next<B>,
) -> Result<ServiceResponse<BoxBody>, Error>
where
B: MessageBody + 'static,
{
if SKIP_PREFIXES
.iter()
.any(|prefix| request.path().starts_with(prefix))
{
return Ok(next.call(request).await?.map_into_boxed_body());
}
let Some(state) = request
.app_data::<Data<AppState>>()
.map(|value| value.get_ref().clone())
else {
return Ok(next.call(request).await?.map_into_boxed_body());
};
let Some(verifier) = request
.app_data::<Data<Arc<jwt::JwtVerifier>>>()
.map(|value| value.get_ref().clone())
else {
return Ok(next.call(request).await?.map_into_boxed_body());
};
let token = read_cookie_header(request.headers(), &state.config.oauth.session_cookie)
.map(str::to_owned);
let Some(token) = token else {
return Ok(next.call(request).await?.map_into_boxed_body());
};
let Ok(claims) = verifier.verify_access(&token).await else {
return Ok(next.call(request).await?.map_into_boxed_body());
};
let Some(session_id) = claims.sid.as_deref().map(str::to_owned) else {
return Ok(next.call(request).await?.map_into_boxed_body());
};
let Some(kenauth) = state.kenauth.as_ref().cloned() else {
return Ok(next.call(request).await?.map_into_boxed_body());
};
let key = format!("oauth:recheck:{}:{}", session_id, claims.security_version);
if export::redis::get_string(&state.redis, &key)
.await
.ok()
.flatten()
.is_some()
{
return Ok(next.call(request).await?.map_into_boxed_body());
}
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;
Ok(next.call(request).await?.map_into_boxed_body())
}
Err(auth::client::error::KenAuthError::Unauthenticated)
| Err(auth::client::error::KenAuthError::NotFound) => {
let mut response = HttpResponse::Unauthorized().json(serde_json::json!({
"code": 401,
"message": "session_revoked",
"data": null,
"error": null,
"error_code": "session_revoked",
"request_id": null,
"log_id": null,
}));
append_cookie(
&mut response,
&jwt::clear_session_cookie(&state.config.oauth),
);
Ok(request.into_response(response))
}
Err(_) => Ok(next.call(request).await?.map_into_boxed_body()),
}
}