Credentials
Migrating from another IAM?
Password hashes from another identity provider can be imported per user and are re-encoded as argon2id at first sign-in. See Export & Import.
A credential is proof of identity. A user can hold several at once, which is what makes multi-factor authentication possible.
Credential types
Password
Passwords are hashed with Argon2id, a memory-hard algorithm chosen because it makes GPU-accelerated brute forcing expensive.
Stored data:
hash_iterations. Argon2 iteration countalgorithm. Hashing algorithm identifiersalt. Unique random salt per credential
Passwords are never stored in plaintext and cannot be retrieved, only verified.
The cost of a new hash is set on the server, through three variables described in the Configuration guide:
| Variable | Default | What it sets |
|---|---|---|
PASSWORD_HASH_MEMORY_KIB | 7168 | Memory per hash, in KiB |
PASSWORD_HASH_ITERATIONS | 5 | Number of iterations |
PASSWORD_HASH_PARALLELISM | 1 | Degree of parallelism |
Verification reads the cost from the stored hash, so changing these values affects only new hashes. At the next successful sign-in, a password whose hash uses another cost, or another algorithm such as bcrypt, is hashed again with the current settings.
TOTP
A shared secret paired with an authenticator app such as Google Authenticator, Authy, or 1Password. Every authenticator is enrolled the same way: HMAC-SHA1, 6 digits, a 30 second step. The enrollment QR code carries those values, so the app needs no setting. FerrisKey accepts the code of the previous, the current and the next step, which absorbs a little clock drift. A user holds one authenticator at a time, and enrolling a new one replaces the old.
The seed is kept in the database. It is sealed only when SECRETS_ENCRYPTION_KEYS is set; with no key it is stored in clear. See Secrets at rest.
TOTP credentials are managed by the Trident module.
WebAuthn passkeys
Hardware security keys and platform authenticators: Touch ID, Windows Hello, Android biometrics. FerrisKey stores the public key and the credential metadata. The private key never leaves the user’s device.
Recovery codes
Backup codes that each work exactly once in place of the normal MFA challenge. FerrisKey does not create them when MFA is set up. A signed-in user asks for a set:
POST /realms/{realm_name}/login-actions/generate-recovery-codes
The body carries an elevation_id, the number of codes in amount, and code_format, for which b32-split-4 is the only value. The elevation has to come from a re-authentication with the password, so a stolen session cannot mint codes by itself; without it the request fails with 403. See Account Security.
The plaintext codes are returned once. They are hashed before storage like any other secret. Generating a new set invalidates the previous one. Recovery Codes covers how they are used.
Federated
The credential model has a variant for a record that points at an external identity provider instead of holding a secret, carrying a provider_id and a provider_type. Nothing in 0.10.0 creates one. A user brought in from an LDAP provider gets a password credential whose stored secret is the literal federated, which tells the login flow to check the password against the directory instead of the database. A user who signs in through a brokered provider such as GitHub has no credential at all: the account is tied to the provider by a link row. Providers are managed through the Abyss module.
Temporary credentials
A credential can be flagged temporary. That is almost always a password, and it triggers the update_password required action: the user has to set a permanent one before getting full access.
Credential lifecycle
A user typically ends up with a password, a TOTP credential once MFA is set up, a set of recovery codes if they asked for one, and possibly one or more WebAuthn passkeys.
An administrator can reset the password and delete any credential from the admin console. Users manage their own credentials through the account console, which asks them to re-authenticate before a sensitive change.