use axum::{ extract::{Extension, State}, http::HeaderMap, response::IntoResponse, }; use module_auth::LogoutCurrentSessionInput; use platform_auth::hash_refresh_session_token; use shared_contracts::auth::LogoutResponse; use time::OffsetDateTime; use crate::{ api_response::json_success_body, auth::{AuthenticatedAccessToken, RefreshSessionToken}, auth_session::{ attach_set_cookie_header, build_clear_refresh_session_cookie_header, map_logout_error, }, http_error::AppError, request_context::RequestContext, state::AppState, }; pub async fn logout( State(state): State, Extension(request_context): Extension, Extension(authenticated): Extension, maybe_refresh_token: Option>, ) -> Result { let refresh_token_hash = maybe_refresh_token.and_then(|token| { let token = token.0.token().trim().to_string(); if token.is_empty() { return None; } Some(hash_refresh_session_token(&token)) }); state .auth_user_service() .logout_current_session( LogoutCurrentSessionInput { user_id: authenticated.claims().user_id().to_string(), refresh_token_hash, }, OffsetDateTime::now_utc(), ) .map_err(map_logout_error)?; let mut headers = HeaderMap::new(); attach_set_cookie_header( &mut headers, build_clear_refresh_session_cookie_header(&state)?, ); Ok(( headers, json_success_body(Some(&request_context), LogoutResponse { ok: true }), )) }