Configuration
The SDK is configured through two structs: AppConfig (HTTP / route-level
concerns) and AuthServiceConfig (JWT / cryptographic concerns). Both are
plain Rust structs — populate them however you like (env vars, TOML, JSON,
hardcoded).
AppConfig
use identsphere_axum::AppConfig;
let cfg = AppConfig {
app_name: "Acme".into(),
public_base_url: "https://auth.example.com".into(),
from_email: "no-reply@example.com".into(),
cookies_secure: true,
route_prefix: "/v1/auth".into(),
refresh_cookie_max_age_secs: 30 * 24 * 60 * 60,
step_up_ttl_secs: 30 * 60,
rp_id: "auth.example.com".into(),
rp_origin: "https://auth.example.com".into(),
rp_name: "Acme".into(),
oauth_google_client_id: Some("...".into()),
oauth_google_client_secret: Some("...".into()),
oauth_github_client_id: Some("...".into()),
oauth_github_client_secret: Some("...".into()),
..Default::default()
};
| Field | Default | Notes |
|---|---|---|
app_name | "IdentSphere" | Shown in email subjects, TOTP issuer. |
public_base_url | http://localhost:3000 | Canonical URL of the host. Used to build links in transactional emails. |
from_email | no-reply@example.com | Sender of transactional emails. Must be a verified address on your sending domain. |
cookies_secure | false | Must be true in production. Toggles the Secure cookie attribute. |
route_prefix | /v1/auth | Path the SDK is mounted under. Scopes the refresh-token cookie. |
refresh_cookie_max_age_secs | 2592000 (30d) | Refresh-cookie lifetime. |
step_up_ttl_secs | 1800 (30 min) | How long a step-up MFA assertion remains valid. |
rp_id | localhost | WebAuthn Relying Party ID. Host of public_base_url, no scheme or port. |
rp_origin | http://localhost:3000 | WebAuthn origin: full URL with scheme. |
rp_name | IdentSphere | User-facing RP name. |
oauth_google_client_id / _secret | None | Optional. If unset, the Google /start endpoint returns 404. |
oauth_github_client_id / _secret | None | Same. |
::: warning cookies_secure in production
cookies_secure = false in production means the session cookie is sent
over plaintext HTTP. Don't ship that.
:::
AuthServiceConfig
use identsphere_core::services::AuthServiceConfig;
let auth_cfg = AuthServiceConfig {
jwt_secret: std::env::var("IDENTSPHERE_JWT_SECRET").expect("set JWT secret"),
issuer: "IdentSphere".into(),
access_expiry_secs: 900, // 15 min
refresh_expiry_secs: 30 * 24 * 60 * 60, // 30 days
..Default::default()
};
| Field | Default | Notes |
|---|---|---|
jwt_secret | (empty) | Required. HS256 signing key. Minimum 32 bytes from a CSPRNG. |
issuer | "IdentSphere" | iss claim on every minted JWT. |
access_expiry_secs | 900 | Access-token TTL. |
refresh_expiry_secs | 2592000 | Refresh-token TTL. Should be ≥ refresh_cookie_max_age_secs. |
::: warning Rotating jwt_secret Rotating the JWT secret invalidates every outstanding session. There is no second-key grace window in v0.1. Plan for forced sign-out when you rotate. :::
Providers (traits)
The SDK ships defaults you can override:
use std::sync::Arc;
use identsphere_core::providers::email::LogOnlySender;
use identsphere_core::providers::storage::LocalFsStorage;
use identsphere_core::providers::cache::PostgresOnlyCache;
let state = AppState {
config: Arc::new(cfg),
db: db.clone(),
auth_service: Arc::new(auth_service),
session_cache: Arc::new(PostgresOnlyCache::new(db.clone())),
email_sender: Arc::new(LogOnlySender),
object_storage: Arc::new(
LocalFsStorage::new("./uploads", "http://localhost:4000/files")
),
// ...
};
| Trait | Default | Production options |
|---|---|---|
EmailSender | LogOnlySender (prints to stdout) | SMTP, Resend, SES, SendGrid — bring your own |
ObjectStorage | LocalFsStorage | S3Storage (S3, R2, MinIO), GcsStorage (GCS) |
SessionCache | PostgresOnlyCache | RedisCache |
Implementing your own is one trait impl each — see the trait docs in
identsphere_core::providers.
Putting it together
use axum::Router;
use identsphere_axum::{routes, AppState};
use std::sync::Arc;
let app = Router::new()
.nest("/v1/auth", routes::auth::router())
.nest("/v1/auth/mfa", routes::mfa::router())
.nest("/v1/users/me", routes::users::router())
// ...
.with_state(state);
The full wiring is in Quick start.
See also
- Environment variables reference — the convention for env-var names that the example app and Docker image use.