use axum::extract::FromRequestParts; use axum::http::header::AUTHORIZATION; use axum::http::request::Parts; use cm_auth::AuthedUser; use crate::{ApiError, AppState}; /// Extracts and verifies the bearer token on protected routes. pub struct Authed(pub AuthedUser); /// Pulls the raw bearer secret out of the Authorization header. pub(crate) fn bearer_secret(parts: &Parts) -> Result<&str, ApiError> { parts .headers .get(AUTHORIZATION) .and_then(|v| v.to_str().ok()) .and_then(|v| v.strip_prefix("Bearer ")) .ok_or(ApiError::Unauthorized) } impl FromRequestParts for Authed { type Rejection = ApiError; async fn from_request_parts( parts: &mut Parts, state: &AppState, ) -> Result { let secret = bearer_secret(parts)?; let user = state.auth.authenticate(secret).await?; Ok(Authed(user)) } }