Local username-and-password is the built-in authentication method. It works for any user, requires no external provider, and is enabled by default. This article covers how it's configured, how passwords are stored, and the policy levers you control.
How Passwords Are Stored
Passwords are never stored in plaintext. The platform hashes them using Argon2id (the current OWASP recommendation) with a per-user salt. Older hashes from migrated systems (bcrypt, PBKDF2) are accepted on sign-in then transparently upgraded.
Policy Settings
- Minimum length: Default 12 characters.
- Character classes: Require uppercase, lowercase, digits and/or symbols.
- Common password rejection: Reject passwords found in HaveIBeenPwned's top breach lists.
- Password history: Prevent re-use of the last N passwords.
- Maximum age: Force a password change every N days (0 = never).
- Maximum failed attempts: Account auto-block threshold.
Policy by Audience
- Internal staff: 14 chars, all character classes, 90-day rotation, history of 12, hard breach-list rejection.
- External customers: 10 chars minimum, no character class requirements (better usability), breach-list still active.
- High-security (e.g. finance team): 16 chars, mandatory 2FA, 30-day rotation.
Worked Examples
- NIST 800-63B alignment: Drop character-class requirements, raise minimum to 14, rely on breach-list rejection and 2FA — modern best practice.
- Legacy migration: Migrating from a system that stored MD5 hashes — set minimum length to current policy, force-change on next sign-in to upgrade hashes.
Warning: Mandatory 90-day rotation is no longer recommended by NIST. It tends to produce predictable passwords like “Spring2026!”. Rely on length, breach detection and 2FA instead.