Skip to main content

Threat model

What IdentSphere defends against, and what it explicitly does not.

In scope

Account takeover via credential stuffing

  • Defense: Argon2id hashing (resists offline brute-force).
  • Defense: TOTP MFA, passkeys.
  • Caller's responsibility: rate-limit /login and /password/forgot (the SDK does NOT ship a built-in rate limiter).
  • Caller's responsibility: pre-validate against breach databases (HIBP) if you need that level of defense.

Account enumeration

  • Defense: /login returns identical errors for unknown email and wrong password.
  • Defense: /password/forgot and /email-otp/request always return 204, regardless of email status.
  • Residual risk: timing attacks. Hosts deeply concerned about timing can add a randomized delay in front of these endpoints.

Session hijacking via XSS

  • Defense: HttpOnly on the access token cookie — JS cannot read it.
  • Defense: short access-token TTL (default 15 min).
  • Caller's responsibility: don't ship XSS bugs. The cookie is not a silver bullet against malicious script with full DOM access.

Session hijacking via CSRF

  • Defense: double-submit CSRF token (identsphere_csrf cookie + matching X-CSRF-Token header on state-changing requests).
  • Defense: SameSite=Lax on session cookies.

Refresh-token theft

  • Defense: tokens rotate on every /refresh. A replayed token finds no row and fails. (Future: replay revokes the family.)
  • Defense: refresh-cookie path scope is route_prefix (default /v1/auth) — the host app's other routes never see this cookie.

MFA bypass via brute force

  • Defense: 5-attempts-per-mfa_token lockout.
  • Defense: TOTP codes are 6 digits with ±1 30-second window — 30 candidates per minute; with 5 attempts per 5-minute token the attacker has a 5e-6 chance of guessing.
  • Defense: recovery codes are single-use, 10 chars alphanumeric ≈ 56 bits of entropy.

Social-OAuth open redirect

  • Defense: redirect_to query parameter is validated to start with / and not start with //.

State-token replay

  • Defense: OAuth state tokens are stored in session_cache with 10-min TTL and burned on use.
  • Defense: MFA tokens carry a jti claim that's burned after use.

Password reset abuse

  • Defense: reset tokens are single-use, 1-hour TTL, SHA-256 hashed in DB.
  • Defense: successful reset revokes ALL active sessions for the user.

Stolen avatar / object-storage abuse

  • Defense: avatar uploads are capped at 5 MiB.
  • Defense: content-type whitelist (JPEG/PNG/GIF/WebP).
  • Caller's responsibility: storage bucket should have proper IAM policies; the SDK doesn't enforce server-side image validation beyond content-type sniffing.

Out of scope

The SDK explicitly does NOT defend against:

Rate limiting

The SDK ships NO rate limiting. Mount your own at the edge (tower-governor, nginx limit_req, Cloudflare, etc.).

Bot detection

No CAPTCHA, no behavioral analytics, no device fingerprinting (beyond the trusted-browser User-Agent binding). Wire your own (hCaptcha, Turnstile, etc.) in front of /register and /login if you need it.

Compromised email accounts

If an attacker controls the user's email inbox, they can:

  • Reset the password.
  • Receive email OTP codes.
  • Accept invitations.

The SDK cannot defend against this — the email is the recovery factor of last resort.

The trusted-browser cookie binds to the User-Agent header but not to the underlying device. An attacker who exfiltrates the cookie AND forges a matching UA can bypass MFA on a fresh session. The 30-day TTL bounds the window; revoking via DELETE /v1/auth/trusted-browsers/:id closes it immediately.

Phishing of TOTP codes

TOTP codes can be phished. The attacker collects email + password + a fresh TOTP code via a fake login page and replays them within 30 seconds. Defense: use passkeys (phishing-resistant) instead of TOTP wherever possible.

DDoS

No DDoS protection. Run IdentSphere behind a CDN that can absorb floods (Cloudflare, Fastly, etc.).

Compromised identsphere-server host

If an attacker gains code execution on the identsphere-server process, they can read every plaintext password, MFA secret, etc. that flows through. Defense in depth here is at the host / infra layer.

Threat actors NOT considered

  • Nation-state actors with side-channel access to the hardware.
  • Insider attackers with DATABASE_URL access.
  • Attackers with access to the Postgres backup tapes.

These are out of scope at every reasonable software layer; encryption at rest, infra hardening, and ops practice are what address them.

Reporting issues

Email security@example.com (host-defined). Standard 90-day responsible disclosure window. PGP key on request.