use crate::Authenticator;
use crate::error::Error;
use axum::extract::{Request, State};
use axum::http::StatusCode;
use axum::middleware::Next;
use axum::response::{IntoResponse, Response};
use axum_extra::{
TypedHeader,
headers::{Authorization, authorization::Bearer},
};
pub async fn authentication_middleware<T: Authenticator>(
State(verifiers): State<T>,
authorization: Option<TypedHeader<Authorization<Bearer>>>,
mut request: Request,
next: Next,
) -> Response {
let Some(authorization) = authorization else {
tracing::debug!("Missing authorization header");
return (StatusCode::UNAUTHORIZED, "Missing authorization header").into_response();
};
let token = authorization.token();
let introspection = crate::introspect::introspect(token);
let auth_result = verifiers.authenticate(token, &introspection).await;
match auth_result {
Ok(auth) => {
request.extensions_mut().insert(auth);
next.run(request).await
}
Err(e) => {
tracing::debug!("Unauthenticated: {:?}", e);
match e {
Error::NoAuthenticatorCanHandleToken => (
StatusCode::UNAUTHORIZED,
"No authenticator can handle the token",
)
.into_response(),
Error::InternalError { .. } => (
StatusCode::INTERNAL_SERVER_ERROR,
"Authentication failed with internal error",
)
.into_response(),
_ => (StatusCode::UNAUTHORIZED, "Unauthenticated").into_response(),
}
}
}
}