Files
WRNexusJS/packages/auth/SECURITY.md
T
2026-07-29 12:51:10 +05:30

5.4 KiB

Authentication security guidance

Required production controls

  1. Use a cryptographically random authentication HMAC secret of at least 32 characters.
  2. Use SqlAuthStore or another durable shared AuthStore; MemoryAuthStore is for development and tests.
  3. Protect TOTP seeds and OAuth tokens with createAuthSecretProtector() and a rotated @wrnexus/encryption keyring.
  4. Queue verification delivery and never log OTP codes, raw one-time tokens, reset URLs, or provider secrets.
  5. Rate-limit registration, login, verification, OTP, reset, magic-link, invitation, passkey, and impersonation endpoints.
  6. Accept CAPTCHA success only from a server-side verifier such as captchaGuard().
  7. Keep package CSRF verification enabled for cookie-authenticated unsafe requests unless an equivalent gateway control replaces it.
  8. Validate every post-authentication redirect as same-origin.
  9. Use HTTPS, Secure and HttpOnly session cookies, an appropriate SameSite policy, strict security headers, and trusted-proxy configuration.
  10. Persist security events in a durable, access-controlled audit sink.
  11. Require a reason and explicit authorization policy for impersonation and show a persistent banner while it is active.
  12. Require recent or step-up authentication before especially sensitive account-management actions when the surrounding product policy demands it.

Passwords and lockout

Passwords use the framework password API. Keep the default 12-character minimum or raise it, and configure a breach provider in production. Browser validation is only a usability layer; server validation and engine policy remain authoritative.

Temporary failed-login locks preserve the previous account state. A valid password reset clears only a failed-login lock; it does not reactivate an administratively locked, disabled, or deleted account.

Tokens and OTP

Reset, verification, invitation, magic-link, and MFA transaction tokens are HMAC-hashed at rest, expire, and are one-use. OTP challenges are bound to verification, login, or MFA purpose and have attempt limits. Email/SMS MFA can use only verified linked identities.

Durable custom stores should consume one-time credentials atomically, preferably in the same transaction as the protected state change. The generic AuthStore interface exposes read/update operations and cannot by itself guarantee compare-and-set behavior across concurrent processes.

Public reset, magic-link, passwordless-OTP, and verification-request endpoints return generic responses to reduce account enumeration. Rate limiting and delivery-abuse controls are still required.

For login forms, pair captchaGuard({ verifiedForMs }) with <Captcha resetOnError="false" /> so a successful human check can survive an incorrect-password retry. The grant remains session-bound and action-bound; authentication rate limits, risk blocking, and account lockout remain required.

Account recovery

Disabled, deleted, and administratively locked accounts cannot complete verification or password recovery with previously issued tokens. Password reset revokes active sessions. Recovery-code regeneration invalidates earlier unused codes.

Sessions and trusted devices

The WRNexusJS session container is regenerated when an auth session is established. Auth sessions have idle and absolute expiry. Trusted-device values should be opaque, stable identifiers generated by the application—not high-entropy browser fingerprint profiles containing unnecessary personal data.

TOTP and recovery codes

TOTP validation rejects reused counters. Encrypt TOTP seeds with secretProtector. Recovery codes are displayed once and stored only as hashes.

Passkeys

The browser runtime does not perform cryptographic verification. The configured PasskeyProvider must verify the challenge, RP ID, exact origin, signature, user presence or verification, counter, and credential ownership. Require HTTPS outside localhost.

The default challenge store is memory-only. Use a shared Redis, SQL, or equivalent PasskeyChallengeStore when requests can reach more than one process. Passkeys are implemented as strong passwordless sign-in; they are not currently a selectable method in the second-step MFA challenge component.

OAuth

Use PKCE, state, nonce, and callback validation from @wrnexus/oauth. Encrypt provider tokens before durable storage. Never auto-link an OAuth account solely from an unverified provider email.

Database integrity

Run both package migrations in order. Production schemas should preserve the included unique constraints for normalized identities, passkey credential IDs, trusted-device fingerprints, token hashes, and OAuth provider account IDs.

Registration and one-time credential state changes should run in transactions when a custom store supports them. This prevents partial writes and concurrent replay beyond what a generic multi-operation store can guarantee.

Impersonation

authorizeImpersonation defaults to deny. Restrict it to named roles, require a reason, preserve the actor session, display ImpersonationBanner, and notify the organization when policy requires it. Apply a separate rule before allowing an actor to impersonate a more privileged target.

Use AuthEngineOptions.tokenUrl to map one-time credentials to application pages. Treat the callback as trusted server configuration, use HTTPS production origins, and do not log raw tokens or generated URLs.