How to add authentication to Axum API

Add authentication to Axum by creating a middleware that validates Bearer tokens in request headers before allowing access to protected routes.

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.