Skip to main content
The AuthLayer is a drop-in Axum middleware that intercepts incoming requests, extracts the Bearer token from the Authorization header, and cryptographically verifies it against your Wacht deployment. If the token is valid, it injects the verified claims into the request extensions, making the user’s identity available to your route handlers. If it is invalid or expired, it automatically rejects the request with a 401 Unauthorized.

Basic Usage

The most common pattern is to apply AuthLayer to a set of protected routes, keeping your public routes separate.
use axum::{Router, routing::get, Json};
use wacht::middleware::{AuthLayer, RequireAuth};

async fn public_route() -> &'static str {
    "Anyone can see this"
}

// The RequireAuth extractor will read the context injected by AuthLayer
async fn protected_route(auth: RequireAuth) -> Json<serde_json::Value> {
    Json(serde_json::json!({
        "user_id": auth.user_id,
        "session_id": auth.session_id
    }))
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    wacht::WachtClient::from_env().await?;

    let app = Router::new()
        .route("/public", get(public_route))
        // Create a nested router for protected endpoints
        .nest("/api", Router::new()
            .route("/protected", get(protected_route))
            // Apply the AuthLayer only to the /api routes
            .layer(AuthLayer::new())
        );

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
    axum::serve(listener, app).await?;
    
    Ok(())
}

Layer Ordering

In Axum (and tower services in general), middleware layers execute from bottom to top. If you are using AuthLayer alongside tracing or CORS middleware, you generally want authentication to happen after logging but before business logic.
use tower_http::trace::TraceLayer;

let app = Router::new()
    .route("/api/data", get(fetch_data))
    .layer(AuthLayer::new())             // Second: Authenticate
    .layer(TraceLayer::new_for_http());  // First: Trace

Extracting the Context Data

While the RequireAuth extractor is the recommended way to access user data, you can also extract the raw AuthContext from the Axum Extension.
use axum::Extension;
use wacht::middleware::AuthContext;

async fn manual_extraction(Extension(auth): Extension<AuthContext>) -> String {
    format!("Hello, user {}!", auth.user_id)
}

Custom Configuration

AuthLayer::new() utilizes your global SDK configuration and applies secure defaults. You can customize these validation rules if necessary.
use wacht::middleware::AuthLayer;

let auth_layer = AuthLayer::new()
    .allowed_clock_skew(10)       // Allow 10 seconds of clock variation across servers
    .validate_exp(true)           // Ensure the token hasn't expired
    .required_issuer("wacht.io"); // Strictly enforce the token's origin