Auth configuration — environment variables (Headless Auth Platform)

This project is the identity provider (HAP). Its env vars configure the server itself — its database, signing keys, issuer identity, admin access, and email delivery. The relying-party apps (website, CRM) do not appear here as config; instead, each app is stored as an application row (client_id + hashed secret + redirect URIs) and each wbsp-style tenant as a tenant row, created via the admin API or the seed script — not via env vars.

All variables use the HAP_ prefix (pydantic-settings env_prefix). For a local source run (uv run uvicorn …) the values live in target/.env. For a platform deploy, non-secret per-environment values are set in wbsp.yaml under destination.<name>.env:, and secrets are declared by reference in wbsp.yaml secrets: with their values in the git-ignored .env.<destination> beside the manifest — each destination reads only its own file (destinations never layer). See also aws-rollout.md.

Variables

VariableWhat it isWhere to get the value
HAP_DATABASE_URLPostgreSQL connection (SQLAlchemy async).Local: docker-compose Postgres (…@localhost:54390/hap). AWS: the platform injects DATABASE_* and derives this automatically — don't set it.
HAP_REDIS_URLRedis connection (rate limits, OTP/challenge state, JWKS cache).Local: docker-compose Redis. AWS: injected as REDIS_* and derived automatically.
HAP_ISSUER_BASE_URLThe public base URL of this platform; tenants' OIDC issuer is {this}/t/{tenant}. Used in iss/aud, discovery, and (this matters) deciding whether the hosted-session cookie is Secure (https ⇒ Secure).Chosen per environment: local http://localhost:8000; AWS https://auth.wbsp-demo.com. Set in wbsp.yaml per destination (destination.<name>.env).
HAP_ADMIN_API_KEYMaster admin key for the admin API (/v1/tenants, /v1/applications, /v1/webhooks, …).You generate it (openssl rand -base64 32), declare it by reference in wbsp.yaml secrets:, and put the value in the git-ignored .env.<destination>. It becomes the admin key on next deploy.
HAP_MASTER_ENCRYPTION_KEYAES key that envelope-encrypts the tenant signing keys stored in the DB (key_provider=db).Generate once (openssl rand -base64 32) and never change it — a new value makes existing signing keys undecryptable and breaks all token signing. Recover the existing one when redeploying.
HAP_KEY_PROVIDERWhere signing keys live: env | db | aws_kms | vault.Local default env; AWS uses db (set in wbsp.yaml).
HAP_ENVIRONMENTdev | staging | prod (affects logging/behaviour).Set per destination in wbsp.yaml.
HAP_EMAIL_MODEconsole (logs OTP codes to stdout — local) or smtp (real email).Local console; AWS smtp.
HAP_EMAIL_FROMFrom-address for OTP/magic-link email (must be SES-verified on AWS).Your verified sender, e.g. no-reply@wbsp.ai.
HAP_SMTP_HOST / _PORT / _USERNAME / _PASSWORD / _STARTTLS / _SSLSMTP relay for email_mode=smtp.AWS SES SMTP endpoint + credentials (SES console → SMTP settings). On the platform these are declared by reference in wbsp.yaml secrets:, with values in each cloud destination's git-ignored .env.<destination> (keys SES_SMTP_USERNAME/SES_SMTP_PASSWORD).
HAP_WEBAUTHN_RP_ID / _RP_NAME / _ORIGINPasskey (WebAuthn) relying-party identity.Bind to the platform's own domain per destination (localhost / auth.wbsp-demo.com).

Per-tenant settings are NOT env vars — they are columns on the tenants row, toggled via the admin API: hosted_login_enabled, passwordless_jit_provisioning (PATCH /v1/tenants/{id}). Applications (the website/CRM clients) are application rows created via POST /v1/applications (or target/scripts/seed_hosted_login.py): client_id, client_secret (returned once, stored hashed), redirect_uris, post_logout_redirect_uris, scopes.

Equivalent names across the three projects

Same concept, different variable name in each project (because each uses a different framework/convention):

ConceptPlatform (this repo, FastAPI)Website (Next.js, custom OIDC)CRM (Next.js, Auth.js)
Platform base URL / issuerHAP_ISSUER_BASE_URLHAP_BASE_URL + HAP_TENANTAUTH_HAP_ISSUER (= {base}/t/{tenant})
Tenanttenants row (slug wbsp)HAP_TENANT (+ HAP_TENANT_ID)encoded in AUTH_HAP_ISSUER path
App client_idapplication.client_idHAP_WEBSITE_CLIENT_IDAUTH_HAP_ID
App client secretapplication.client_secret_hash (hashed)HAP_WEBSITE_CLIENT_SECRETAUTH_HAP_SECRET
Redirect / callback URIapplication.redirect_urisHAP_WEBSITE_REDIRECT_URIderived {AUTH_URL}/api/auth/callback/hap
Post-logout URIapplication.post_logout_redirect_urisHAP_WEBSITE_POST_LOGOUT_REDIRECT_URIderived {NEXT_PUBLIC_APP_URL}/login
"Login via platform" toggletenant.hosted_login_enabledHAP_AUTH_ENABLEDNEXT_PUBLIC_HAP_ENABLED (+ AUTH_HAP_ISSUER present)
This app's own public URLHAP_ISSUER_BASE_URLAPP_BASE_URLAUTH_URL (+ AUTH_TRUST_HOST) / NEXT_PUBLIC_APP_URL
Local session signing secretn/a (issues tenant-signed tokens)AUTH_SECRETAUTH_SECRET
Admin API keyHAP_ADMIN_API_KEYHAP_ADMIN_KEY (access-control calls)n/a
Webhook signing secretwebhook.signing_secretHAP_WEBHOOK_SECRETn/a
In-cluster service host (AWS)n/aHEADLESS_AUTH_AUTH_HOST/_PORT (injected)HEADLESS_AUTH_AUTH_HOST/_PORT (injected)
At-rest encryption keyHAP_MASTER_ENCRYPTION_KEY (signing keys)n/aENCRYPTION_KEY (stored OAuth tokens)