# 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 `` 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. ## Delivered links 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.