Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rullst Auth

rullst-auth provides Argon2id password hashing, versioned AES-GCM cookie sessions, role-based authorization middleware, WebAuthn/passkey ceremony verification, and an opt-in application JWT policy.

Application JWTs are enabled with jwt. The sqlite feature also enables JWT and adds durable shared JWT revocation plus passkey device state. OAuth2/OIDC providers remain a separate trust boundary enabled with oauth, which re-exports rullst-connect.

Passwords

Use the asynchronous functions inside HTTP handlers so Argon2 work runs on Tokio’s blocking pool:

#![allow(unused)]
fn main() {
use rullst_auth::{AuthError, hash_password_async, verify_password_async};

async fn verify_login(password: String) -> Result<bool, AuthError> {
    let hash = hash_password_async(password.clone()).await?;
    Ok(verify_password_async(password, hash).await)
}
}

Passwords longer than 72 bytes are rejected. needs_rehash compares the algorithm, version, memory, iteration, and parallelism parameters.

Encrypted sessions

make_login_cookie and decrypt_session use a versioned AES-256-GCM envelope with authenticated metadata and an operating-system nonce. APP_KEY must contain at least 32 bytes, must not be a documented placeholder, and must satisfy the entropy check.

#![allow(unused)]
fn main() {
use rullst_auth::{AuthError, decrypt_session, get_app_key, make_login_cookie};

fn round_trip(user_id: i32) -> Result<i32, AuthError> {
    let cookie = make_login_cookie(user_id)?;
    let token = cookie
        .split(';')
        .next()
        .and_then(|part| part.split_once('='))
        .map(|(_, value)| value)
        .ok_or_else(|| AuthError::General("session cookie is malformed".to_string()))?;
    decrypt_session(token, &get_app_key()?)
}
}

WebAuthn/passkeys

PasskeyAuth validates exact RP origin and ID binding, one-time expiring challenges, client-data ceremony type, user-presence/user-verification flags, ES256 COSE keys, P-256 points, credential IDs, signatures, and monotonic counters. Only none attestation is advertised and accepted. With sqlite, SqlitePasskeyStore supplies bounded file-backed registration, listing, renaming, revocation and optimistic counter CAS shared by processes on the same SQLite file. finish_authenticate verifies the ES256 ceremony and atomically advances the stored counter; a stale concurrent update fails. Revoked records remain in inventory and continue to consume quota.

Challenge state remains process-local inside PasskeyAuth, so a multi-instance deployment needs sticky ceremony routing or a custom shared challenge layer. The adapter does not establish normative WebAuthn conformance, encrypt or replicate the database, or replace application device-ownership policy.

Application JWTs

The jwt feature provides ApplicationJwtPolicy, versioned HS256 claims, strong key validation, required issuer/audience/subject/time/JTI claims, bounded TTL and scope policy, and kid-based key rotation. Every verification receives a JwtRevocationStore. Production policies reject the bundled bounded in-memory store because it is process-local. With sqlite, SqliteJwtRevocationStore persists token IDs and monotonic subject session versions behind a stored quota. Its BEGIN IMMEDIATE mutations are visible to local processes, expired token rows are pruned before capacity checks, and ApplicationJwtPolicy::verify_async checks that shared state.

The SQLite boundary is durable across restarts but not replicated across hosts. The deployment owns trusted paths, file permissions/encryption, backup, availability and disaster recovery. This API does not verify third-party OAuth/OIDC tokens or provide refresh tokens.

RBAC

Implement HasRole for the authenticated user type and install RequireRoleLayer::<User>::new("Admin"). Authentication middleware must insert that user into Axum request extensions before the role layer executes.

OAuth2/OIDC

Enable oauth for the rullst_auth::connect re-export. Provider configuration, discovery, JWKS rotation, and deterministic offline fixtures are implemented by rullst-connect.

Security-sensitive functions return typed errors or a false verification result. The repository’s zero-panic CI checks production library paths; this policy is not an absolute guarantee about all dependencies or host failures.