Authentication security
The authentication surface in depth — the layered request checks, JWT and session model, two-factor challenges, and the hardening applied to every login attempt.
This page covers gate 1 of the two-gate model: proving who you are. Authentication is deliberately layered — every request passes an ordered set of checks, tokens are revocable, and the login endpoint itself is hardened against brute force, timing, and enumeration attacks.
Layered request checks#
Every API request passes the same checks, in a fixed order, before it can reach the application:
- Source reputation — requests from blocked IPs are rejected with
403before any credential is examined (see Abuse protection). - Token validation — the login token is read from cookie or header, its signature is verified, and it is checked against the revocation list before any identity is trusted.
- Session validation — the active server-side session is verified, per-IP rate limiting is applied, and hijacking signals (IP change, user-agent change, geographic anomaly) are detected.
A further, vault-scoped check enforces gate 2 (X-Vault-Session) on vault-data endpoints —
holding a valid login token alone never grants access to vault content.
JWT and session model#
Authentication is stateless (JWT) backed by stateful session records:
| Client | JWT lifetime | Refresh token | Notes |
|---|---|---|---|
| Web | 1 hour | 7 days | Session extended on activity |
| Web (remember me) | 30 days | 60 days | Opt-in |
| Mobile | 24 hours | 60 days | Optional single-session-per-device enforcement |
- Every token carries a unique
jti(JWT ID), enabling server-side revocation via a blacklist that is checked on every validation, with automatic cleanup of expired entries. - Session records track activity asynchronously and are bound to platform-specific expiry.
- Cookies are
Secure,HttpOnly, andSameSite-restricted. - Concurrent sessions per account are capped, with session-fixation protection and session-creation rate limiting.
Two-factor challenges#
After a correct password, the server decides whether a second factor is required based on device trust: a trusted device signs in directly; an unknown device receives a challenge.
| Method | Mechanism |
|---|---|
| TOTP | Authenticator-app codes (RFC 6238), enrolled via QR code |
| Identification code | User-defined backup secret, stored as a BCrypt hash |
| Email OTP | One-time code with bounded TTL and rate limiting |
Challenge tokens are short-lived (5 minutes). Successful completion can establish device trust, subject to per-plan device limits and a configurable trust duration. Manage methods in Two-factor authentication.
Login hardening#
- Progressive delays — exponential backoff on failed attempts, so each successive guess costs the attacker more.
- Timing normalization — auth responses are padded to a minimum duration to close timing side-channels.
- Enumeration protection — failures always return the same "invalid email or password" regardless of which factor failed.
- Password policy — minimum length plus upper/lower/digit/special requirements and a common-password blocklist; the last 5 passwords cannot be reused.
- Account lockout — independent of IP blocking, an account locks after sustained failures.
- Bot filtering — suspicious user agents are rejected at the auth surface.
All responses carry OWASP-aligned security headers: CSP, HSTS, X-Frame-Options: DENY,
X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy, and strict
origin-validated CORS.
Related#
- Abuse protection — IP blocking and replay defense
- Trusted-device unlock — gate 2 without typing keys
- Active sessions — managing your active sessions