Edit Page

Security

RESTHeart Cloud

This 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-password always returns 202 Accepted regardless of whether the email is registered. The response body is the same in all cases.

  • POST /auth/register returns 409 Conflict for 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: $unset from 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).

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, S256 method) is used on every OAuth initiation. The code_verifier is never sent to the browser — it is server-side only.

  • state is validated with constant-time comparison on callback.

  • oauth_codes documents 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

/auth/activate

PATCH

Invalid or expired invite token

/auth/reset-password

PATCH

Invalid or expired reset token

/auth/verify

GET

Redirect to error=invalid_token or error=token_expired

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