Add authentication to an Axum API by creating a custom extractor that validates a Bearer token and applying it as a middleware guard to your routes.
use axum::{
extract::{Extension, Request, State},
http::StatusCode,
middleware::Next,
response::Response,
Json,
};
use serde::Deserialize;
use std::sync::Arc;
#[derive(Deserialize)]
struct AppState {
valid_token: String,
}
struct AuthGuard;
async fn auth_middleware(
Extension(state): Extension<Arc<AppState>>,
mut req: Request,
next: Next,
) -> Result<Response, StatusCode> {
let auth_header = req
.headers()
.get("Authorization")
.and_then(|v| v.to_str().ok())
.unwrap_or("");
if !auth_header.starts_with("Bearer ") {
return Err(StatusCode::UNAUTHORIZED);
}
let token = auth_header.strip_prefix("Bearer ").unwrap();
if token != state.valid_token {
return Err(StatusCode::UNAUTHORIZED);
}
Ok(next.run(req).await)
}
#[tokio::main]
async fn main() {
let state = Arc::new(AppState {
valid_token: "secret123".to_string(),
});
let app = axum::Router::new()
.route("/protected", axum::routing::get(|| async { "Secret Data" }))
.layer(axum::middleware::from_fn(auth_middleware))
.layer(Extension(state));
println!("Listening on http://0.0.0.0:3000");
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Send a request with the header Authorization: Bearer secret123 to access /protected.