Skip to main content

Production checklist

Walk through this list before flipping the auth backend to production.

Secrets

  • IDENTSPHERE_JWT_SECRET is at least 32 bytes from a CSPRNG (openssl rand -hex 32).
  • IDENTSPHERE_JWT_SECRET is distinct from every other environment (dev, staging, per-customer).
  • IDENTSPHERE_JWT_SECRET is sourced from a secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault), NOT a checked-in file.
  • OAuth client secrets are likewise stored in a secrets manager.
  • Database connection strings include sslmode=require (or stricter).

Cookies + transport

  • IDENTSPHERE_COOKIES_SECURE=true.
  • The auth backend is fronted by HTTPS — TLS terminates at the load balancer / ingress / CDN.
  • IDENTSPHERE_PUBLIC_BASE_URL is the canonical HTTPS URL (https://auth.example.com, not http://, not the load-balancer's DNS name).

Database

  • Postgres 14 or newer.
  • IDENTSPHERE_SCHEMA is pre-created (CREATE SCHEMA identsphere;).
  • identsphere migrate up has been run.
  • Database backups are configured AND verified via restore.
  • Audit log retention policy is documented (DELETE FROM IdentSphere.audit_logs WHERE created_at < ...) and scheduled.

Email

  • A real EmailSender implementation is wired up (NOT LogOnlySender).
  • IDENTSPHERE_FROM_EMAIL is a verified address on a domain you control.
  • Reverse DNS / SPF / DKIM / DMARC are configured for the sending domain.
  • You've sent a test password-reset to a real inbox and verified it arrives.

WebAuthn / passkeys

  • IDENTSPHERE_RP_ID matches IDENTSPHERE_PUBLIC_BASE_URL's host (no scheme, no port).
  • IDENTSPHERE_RP_ORIGIN matches the full URL including scheme.
  • You've enrolled one passkey and signed in with it from a clean browser to verify the configuration.

OAuth

  • Google: redirect URI {public_base_url}/v1/auth/oauth/google/callback is registered in the Google Cloud console.
  • GitHub: same callback URL is registered in the GitHub OAuth App settings.
  • You've completed a successful round-trip through each configured provider.

CORS

  • If the auth backend and frontend are on different origins, CORS is configured explicitly (no Access-Control-Allow-Origin: *).
  • Access-Control-Allow-Credentials: true.
  • The frontend uses credentials: 'include' (or axios withCredentials).

Rate limiting

  • POST /v1/auth/login is rate-limited (mount tower-governor or use your edge's rate limiter — Cloudflare, nginx limit_req, etc.).
  • POST /v1/auth/password/forgot is rate-limited.
  • POST /v1/auth/email-otp/request is rate-limited.
  • POST /v1/auth/register is rate-limited (defends against signup spam).

Avatar uploads

  • Object storage is configured (S3 / R2 / GCS / MinIO), NOT LocalFsStorage.
  • The 5 MiB body-size limit is preserved (don't lift it on the ingress / nginx).
  • CDN / cache strategy for avatar_url is decided.

Observability

  • Structured logs (tracing) flowing to a central log store.
  • Health-check endpoint wired into the orchestrator (Kubernetes, Fargate, etc.).
  • At minimum these metrics are alerted on:
    • p95 latency on /v1/auth/login
    • 5xx rate on any endpoint
    • 401 rate on /v1/auth/login (credential-stuffing signal)
    • 429 rate on /v1/auth/mfa/challenge
  • Audit-log queries are wired into your SIEM.

Operational

  • identsphere migrate up is in the deploy pipeline BEFORE the new app version goes live.
  • Rolling deploys verified — zero-downtime restarts.
  • Multiple replicas for HA. (Stateless service; share DB.)
  • Redis (or other shared cache) configured for session_cache if you're running > 1 replica AND care about cache consistency.
  • Runbook documented for IDENTSPHERE_JWT_SECRET rotation (knows that every session will be forced to sign out).
  • Privacy policy reflects the data the SDK stores (email, password hash, MFA secret, audit log).
  • Cookie consent banner if your jurisdiction requires one — the SDK's session cookies are functional / strictly necessary in most frameworks but verify with counsel.
  • Data-deletion process documented and tested ("right to be forgotten") — see Data export.

Smoke tests

After deploying, run these against the production endpoint:

# Registration round-trip
curl -X POST https://auth.example.com/v1/auth/register \
-H 'Content-Type: application/json' \
-d '{"email":"smoke@example.com","password":"smoke-test-password","organization_name":"Smoke"}' \
-c /tmp/c.txt

# Session check
curl https://auth.example.com/v1/auth/session -b /tmp/c.txt

# Logout
curl -X POST https://auth.example.com/v1/auth/logout -b /tmp/c.txt -c /tmp/c.txt

# Confirm logout
curl -i https://auth.example.com/v1/auth/session -b /tmp/c.txt # expect 401

All four should hit the success path. If they don't, fix before letting real users in.