Skip to main content
When a user successfully authenticates and establishes a session, Wacht issues a JSON Web Token (JWT). This token serves as a portable identity proof containing standardized claims about the user and their permissions. If you are using the axum feature, you can automatically extract these claims from validated requests using the RequireAuth extractor.

Claim Extraction Example

The easiest way to work with token claims is to use the RequireAuth extractor in your Axum route handlers. This guarantees the token is valid, unexpired, and properly signed.
use axum::{routing::get, Router};
use wacht::middleware::RequireAuth;

async fn get_profile(auth: RequireAuth) -> String {
    // Basic identifying claims
    let user_id = auth.user_id;        // e.g., "user_123"
    let session_id = auth.session_id;  // e.g., "sess_abc"
    
    // Organization context (if the session is scoped to an org)
    if let Some(org_id) = auth.organization_id {
        return format!("User {} acting on behalf of Org {}", user_id, org_id);
    }

    format!("Personal session for User {}", user_id)
}

Available Claims

By default, the SDK parses the following standard Wacht claims:

Identity & Session

sub
string
The Subject identifier. In Wacht, this is the user’s stable and globally unique user_id. (Available on extractor as auth.user_id).
session_id
string
The unique identifier for the specific authentication session. If the user revokes this session remotely, this token becomes invalid regardless of expiration.

Tenancy & Permissions

organization_id
string | null
If the user has selected an active organization context, this claim will contain the org_id.
organization_permissions
string[] | null
A list of permission strings (e.g., ["users:read", "billing:manage"]) the user holds within the current organization_id.
workspace_id
string | null
If the user has selected an active workspace context within an organization, this claim will contain the workspace_id.
workspace_permissions
string[] | null
A list of permission strings the user holds within the current workspace_id.

Standard JWT Claims

The SDK also strictly verifies standard JWT claims:
  • exp: Expiration Time (enforced automatically, with a 5-second default clock skew allowance).
  • iat: Issued At Time.
  • iss: Issuer (should match your deployment’s Frontend API URL).

Permission Checks

Rather than parsing the permissions vectors manually, the RequireAuth extractor provides convenient methods for permission validation:
use axum::http::StatusCode;
use wacht::middleware::RequireAuth;

async fn delete_project(auth: RequireAuth) -> Result<&'static str, StatusCode> {
    // Check if the user has a specific permission in their current context
    if !auth.has_permission("projects:delete") {
        return Err(StatusCode::FORBIDDEN);
    }
    
    Ok("Project deleted")
}
By understanding how Wacht packages session state into JWT claims, you can build completely stateless, highly scalable API backends in Rust without needing to perform a database lookup for every incoming request.