Skip to main content
While AuthLayer and PermissionLayer provide route-level protection, you often need to access the authenticated user’s identity or verify specific permissions dynamically within the body of your handler. Wacht provides several Axum Extractors for this purpose.

RequireAuth

RequireAuth is the primary extractor you will use. It guarantees that the incoming request has a valid, unexpired session token. If a request reaches a handler asking for RequireAuth without a valid token, Axum will automatically reject the request with a 401 Unauthorized before your handler code even executes.
use wacht::middleware::RequireAuth;

async fn create_post(auth: RequireAuth) -> String {
    // We are guaranteed that `auth.user_id` is a valid string
    format!("Post created by user {}", auth.user_id)
}
The RequireAuth struct contains the entire parsed session context, including helper methods for checking permissions:
use axum::http::StatusCode;
use wacht::middleware::RequireAuth;

async fn delete_project(auth: RequireAuth) -> Result<String, StatusCode> {
    // Check if the user has a specific permission in their active workspace
    if !auth.has_permission("projects:delete") {
        return Err(StatusCode::FORBIDDEN);
    }
    
    Ok(format!("Deleted by {}", auth.user_id))
}

OptionalAuth

For endpoints that behave differently depending on whether the user is logged in (e.g., an article that shows comments only to members), use OptionalAuth.
use wacht::middleware::OptionalAuth;

async fn view_article(auth: OptionalAuth) -> String {
    match auth {
        OptionalAuth(Some(context)) => {
            format!("Welcome back, {}! Here are the comments.", context.user_id)
        }
        OptionalAuth(None) => {
            "Please log in to see comments on this article.".to_string()
        }
    }
}

RequirePermission Macro

If a specific handler strictly requires a specific permission, and you don’t want to use the PermissionLayer at the router level, you can define type-safe custom extractors using the require_permission! macro. This macro generates a new Extractor type that automatically checks for the specified permission and rejects the request with a 403 Forbidden if the user doesn’t have it.
use wacht::require_permission;
use wacht::middleware::PermissionScope;

// Generates a `CanManageBilling` struct
require_permission!(
    CanManageBilling, 
    "billing:manage", 
    PermissionScope::Organization
);

// The handler will ONLY run if the user is authenticated 
// AND has the "billing:manage" permission in their active organization.
async fn view_invoices(_auth: CanManageBilling) -> &'static str {
    "Here are your invoices"
}

Best Practices

  • Use Middleware Layers (AuthLayer, PermissionLayer) when protecting entire groups of routes (e.g., all routes under /api/admin).
  • Use Extractors (RequireAuth) when your business logic needs the user’s ID or when checking dynamic permissions (e.g., does this user own this specific resource?).