Tracking issue for implementing ADR-0069: Enterprise authentication hardening (merged in #2275). Design is accepted-in-principle; no code yet — this issue tracks the phased build.
Parent: #2246 (first-run admin experience). Governing constraint: ADR-0049 — every setting ships with its runtime enforcement; no "false surface" toggles.
Each item = (setting → enforcement seam → mechanism). [native] = better-auth 1.6.x knob; [custom] = ObjectStack hook/middleware; [field] = new identity column.
P1 — security floor (first real customers)
P2 — defense in depth
P3 — federation breadth
Out of scope (separate issues/ADRs)
- SCIM / directory provisioning & bulk import (separate ADR — provisioning ≠ auth).
- Passkeys / WebAuthn.
Suggested first PR: haveibeenpwned (native, low-risk) as the enforcement-wired pattern template, then the [custom] items each with their hook + tests.
Tracking issue for implementing ADR-0069: Enterprise authentication hardening (merged in #2275). Design is accepted-in-principle; no code yet — this issue tracks the phased build.
Parent: #2246 (first-run admin experience). Governing constraint: ADR-0049 — every setting ships with its runtime enforcement; no "false surface" toggles.
Each item = (setting → enforcement seam → mechanism).
[native]= better-auth 1.6.x knob;[custom]= ObjectStack hook/middleware;[field]= new identity column.P1 — security floor (first real customers)
[native]— enablehaveibeenpwnedplugin (password_reject_breached). Lowest-risk first PR / sample for the pattern.[custom]—password_require_complexity+password_min_classes, validated inbeforehooks on/sign-up/email,/reset-password,/change-password.[custom][field]—password_expiry_days(gate at session validation),password_history_count(reject reuse); fieldssys_user.password_changed_at,sys_account.previous_password_hashes.[custom][field]—lockout_threshold+lockout_duration_minutes; fieldssys_user.failed_login_count,locked_until; admin Unlock action + locked-accounts filter.[native]— enable/tune better-auth corerateLimitwith strictercustomRulesfor/sign-in|sign-up|reset; shared store for multi-node.[custom][field]—mfa_required+mfa_grace_period_days; gate password-only sessions at session validation until TOTP enrolled+verified; fieldsys_user.mfa_required_at.P2 — defense in depth
[custom][field]— idle timeout, absolute max, concurrent cap; fieldssys_session.last_activity_at,revoked_at,revoke_reason.[custom][field]—sys_organization.allowed_ip_ranges(+ optional per-user); Hono auth-route middleware before the better-auth handler.[native]— surface admin-managed OIDC providers (issuer/client/scopes/allowed domains) instead of env-onlygenericOAuth.P3 — federation breadth
@better-auth/ssovs custom plugin. Do not ship a SAML settings surface before an enforcing impl (ADR-0049).Out of scope (separate issues/ADRs)
Suggested first PR:
haveibeenpwned(native, low-risk) as the enforcement-wired pattern template, then the[custom]items each with their hook + tests.