Security
RESTHeart CloudThis page documents the security design decisions in restheart-accounts.
Timing-attack mitigation
All token comparisons (invite tokens, verification tokens, password reset tokens, OAuth state) use constant-time string comparison. This prevents an attacker from inferring valid token prefixes by measuring response latency.
Standard string equality (String.equals) short-circuits on the first mismatch and leaks timing information. restheart-accounts uses MessageDigest.isEqual on the SHA-256 digests of both values — a standard constant-time technique.
Account enumeration prevention
-
POST /auth/forgot-passwordalways returns202 Acceptedregardless of whether the email is registered. The response body is the same in all cases. -
POST /auth/registerreturns409 Conflictfor duplicate emails — this is a deliberate trade-off: registration UX requires telling the user the address is taken so they can recover their account.
Token design
All tokens (invite, verification, password reset, OAuth state) are:
-
Generated with
SecureRandom(256-bit entropy — equivalent to a UUIDv4 but longer). -
Single-use:
$unsetfrom the user document on first successful consumption. -
Scoped TTLs: invite and verification tokens expire after 7 days; password reset tokens after 1 hour; OAuth state after 600 seconds (MongoDB TTL index).
Password policy
Password strength is enforced server-side using the zxcvbn algorithm (Dropbox) at the point of:
-
Registration (
POST /auth/register) -
Invitation activation (
PATCH /auth/activate) -
Password reset (
PATCH /auth/reset-password)
The minimum score is configurable (minimumPasswordStrength, default 3 = "Strong").
Client-side zxcvbn checks are encouraged as UX guidance but are not trusted as security controls.
Session hygiene
Before issuing a JWT on invitation activation, the server clears any existing session. This prevents a logged-in user from accidentally activating an invitation as a different identity (session fixation variant).
Legal consent versioning
Consent tracking (terms & conditions, privacy policy versions) is not handled by the Accounts plugin. See Consents Management for guidance on implementing custom consent tracking. === Google OAuth security
-
PKCE (RFC 7636,
S256method) is used on every OAuth initiation. Thecode_verifieris never sent to the browser — it is server-side only. -
stateis validated with constant-time comparison on callback. -
oauth_codesdocuments auto-expire after 600 seconds via a MongoDB TTL index; they are also deleted immediately on use.
Brute-force protection
restheart-accounts relies on RESTHeart’s built-in bruteForceAttackGuard (sliding-window rate limiter per IP) for protection against token-guessing and credential stuffing.
Login endpoint
Failed login attempts on POST /token are counted automatically by the standard auth pipeline and trigger the guard.
Token-verification endpoints
Failed token checks on the following endpoints return 401 Unauthorized and are counted into the same AUTH metric registry via the built-in tokenFailedAuthInterceptor:
| Endpoint | Method | Counted when |
|---|---|---|
|
|
Invalid or expired invite token |
|
|
Invalid or expired reset token |
|
|
Redirect to |
Structural errors (missing fields, malformed JSON) still return 400 Bad Request and are not counted — only genuine token-guess failures feed the guard.
Configure bruteForceAttackGuard in restheart.yml:
/bruteForceAttackGuard/enabled: true
/bruteForceAttackGuard/max-failed-attempts: 5
/bruteForceAttackGuard/trust-x-forwarded-for: true # set false if no reverse proxy