6 releases
| 0.2.0 | Jan 3, 2026 |
|---|---|
| 0.1.10 | Jan 1, 2026 |
| 0.1.9 | Dec 31, 2025 |
#334 in Authentication
67 downloads per month
Used in threatflux-google-sdk
1MB
23K
SLoC
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_postgresorAuthState::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-utilsfeature).
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-configurationand/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/clientsto create a client (returns the client secret once)GET /api/v1/admin/oauth/clientsto list clientsGET/PATCH /api/v1/admin/oauth/clients/{client_id}to inspect or updatePOST /api/v1/admin/oauth/clients/{client_id}/rotate-secretto 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.
Dependencies
~97MB
~1.5M SLoC