threatflux-auth-sdk

Crates.iothreatflux-auth-sdk
lib.rsthreatflux-auth-sdk
version0.2.0
created_at2025-12-07 14:35:00.951693+00
updated_at2026-01-03 15:12:40.818115+00
descriptionReusable authentication SDK for ThreatFlux services
homepagehttps://github.com/ThreatFlux/core
repositoryhttps://github.com/ThreatFlux/core
max_upload_size
id1971696
size897,387
Wyatt Roersma (wroersma)

documentation

https://docs.rs/threatflux-auth-sdk

README

threatflux-auth-sdk

Overview

threatflux-auth-sdk is the reusable authentication and authorization layer shared by ThreatFlux services. It exposes:

  • AuthState, which wraps the configured credential store, token signer, and OAuth hooks
  • ready-to-mount Axum routers for login flows, device/OAuth handshakes, password or token issuance
  • validation + model helpers that keep UI templates, APIs, and CLI clients in sync

The crate is designed to drop into any backend that needs a turnkey auth subsystem with consistent APIs and models.

When to use it

  • Embedding the full auth API into an Axum project via threatflux_auth_sdk::router().
  • Managing secrets/tokens from automation by calling the exported service layer directly.
  • Bootstrapping new stores (Postgres vs in-memory) through AuthState::with_postgres or AuthState::in_memory.
  • Generating OpenAPI documentation for auth routes (threatflux_auth_sdk::AuthApiDoc).

Key capabilities

  • Password + email logins, refresh-token rotation, and OAuth callback handling.
  • Extensible store trait with both in-memory and SQLx/Postgres implementations.
  • OAuth hooks so surrounding applications can react to login/logout lifecycle events.
  • Comprehensive validation logic (password policy, email formats, identifier normalization).
  • Shared data models for users, sessions, organizations, and API tokens.
  • Test utilities that provision seeded stores for integration tests (test-utils feature).

Core packages

  • axum, tower, tokio: request routing and async runtime.
  • sqlx: Postgres-backed persistence for users, sessions, OAuth states, and password resets.
  • argon2, jsonwebtoken, oauth2, rand, sha2, base64: credential hashing + token signing.
  • serde, validator, chrono, uuid: strongly typed request payloads and validation helpers.
  • thiserror, anyhow, tracing, utoipa: ergonomic errors, logging, and OpenAPI support.

Crate layout

crates/threatflux-auth-sdk/
├── src/
│   ├── handlers.rs        # Axum handlers and router() definition
│   ├── service.rs         # Business logic shared across transports
│   ├── state.rs           # AuthState + Postgres/in-memory configuration
│   ├── store/             # ProviderStore trait + memory/postgres backends
│   ├── oauth/             # OAuth-specific helpers + provider glue
│   ├── hooks.rs           # Callback definitions for login/logout events
│   ├── models.rs          # Request/response structs and DB entities
│   ├── validation.rs      # Field + password validators
│   ├── extractor.rs       # Authenticated user extractor for Axum handlers
│   └── openapi.rs         # `AuthApiDoc` builder used by services
├── tests/                 # Postgres integration tests + router smoke tests
└── Cargo.toml             # feature flags (`test-utils`) and dependency declarations

Usage snippet

use threatflux_auth_sdk::{router, AuthState};
use threatflux_auth_sdk::store::PostgresStoreConfig;

#[tokio::main]
async fn main() -> Result<(), threatflux_auth_sdk::AuthError> {
    dotenvy::dotenv().ok();
    let secret = std::env::var("AUTH_SECRET").expect("set AUTH_SECRET");

    let auth_state = if let Ok(db_url) = std::env::var("DATABASE_URL") {
        let config = PostgresStoreConfig::new(db_url);
        AuthState::with_postgres(secret, config).await?
    } else {
        AuthState::in_memory(secret)
    };

    let app = axum::Router::new()
        .merge(router())
        .layer(axum::Extension(auth_state));

    axum::Server::bind(&"127.0.0.1:4000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
    Ok(())
}

Development + testing

# format + lint
cargo fmt -p threatflux-auth-sdk
cargo clippy -p threatflux-auth-sdk --all-targets

# run unit + integration tests (requires Postgres for the `postgres_*` suites)
cargo test -p threatflux-auth-sdk

Set DATABASE_URL when running tests so the SQLx-backed routes exercise the full store implementation. When Postgres is unavailable the suite automatically skips the heavy integration tests and continues with the in-memory coverage.

OAuth configuration

The SDK supports GitHub plus any number of generic OAuth/OIDC providers configured via environment variables. List provider ids in OAUTH_PROVIDERS (comma separated). Each id uses uppercased env prefixes such as OAUTH_TARGET_* or OAUTH_CUSTOM_*:

OAUTH_PROVIDERS=target,custom
OAUTH_TARGET_CLIENT_ID=...
OAUTH_TARGET_CLIENT_SECRET=...
OAUTH_TARGET_AUTH_URL=...
OAUTH_TARGET_TOKEN_URL=...
OAUTH_TARGET_REDIRECT_URI=...
OAUTH_TARGET_USERINFO_URL=...
OAUTH_TARGET_SCOPES=openid profile email           # optional, defaults to these
OAUTH_TARGET_EMAIL_CLAIMS=mail,email               # optional claim names (comma/space separated)
OAUTH_TARGET_USERNAME_CLAIMS=preferred_username    # optional
OAUTH_TARGET_DISPLAY_NAME_CLAIMS=name,firstname,lastname
OAUTH_TARGET_GROUP_CLAIMS=groups,memberof

OAUTH_CUSTOM_CLIENT_ID=...
# ... same keys for each provider id listed in OAUTH_PROVIDERS

GitHub continues to use the existing OAUTH_GITHUB_* variables and scopes appropriate for its API.

Built-in OAuth provider

The SDK can also act as an OAuth2/OIDC provider when enabled via environment variables:

OAUTH_PROVIDER_ENABLED=true
OAUTH_PROVIDER_ISSUER=https://auth.example.com
OAUTH_PROVIDER_SIGNING_KEY=super-secret-signing-key
OAUTH_PROVIDER_SIGNING_ALG=HS256                 # optional, HS256/HS384/HS512
OAUTH_PROVIDER_GRANTS=authorization_code,refresh_token,client_credentials
OAUTH_PROVIDER_SCOPES=openid,profile,email,groups,offline_access
OAUTH_PROVIDER_ACCESS_TTL=3600                   # seconds
OAUTH_PROVIDER_REFRESH_TTL=1209600               # seconds
OAUTH_PROVIDER_KID=provider-key-1                # optional

Exposed endpoints when enabled:

  • /api/v1/oauth/authorize – authorization code with optional PKCE (requires authenticated user with internal access token)
  • /api/v1/oauth/token – authorization_code, refresh_token, and client_credentials grants
  • /api/v1/oauth/userinfo – OIDC user claims derived from the internal user record
  • /api/v1/.well-known/openid-configuration and /api/v1/.well-known/jwks.json

OAuth clients are stored in the same backing store. Admin routes (require an admin user token):

  • POST /api/v1/admin/oauth/clients to create a client (returns the client secret once)
  • GET /api/v1/admin/oauth/clients to list clients
  • GET/PATCH /api/v1/admin/oauth/clients/{client_id} to inspect or update
  • POST /api/v1/admin/oauth/clients/{client_id}/rotate-secret to issue a new secret

Clients can be public (PKCE-only) or confidential (secret-based). Scopes are validated against each client's allowed scopes and the provider-wide grant whitelist.

Commit count: 0

cargo fmt