@1auth/authn-recovery-codes
Backup recovery codes for account access when primary credentials are unavailable.
Install
npm i @1auth/authn-recovery-codes Usage
import recoveryCodes from '@1auth/authn-recovery-codes'
recoveryCodes() Configuration
Recovery codes use sensible defaults:
- Entropy: 128 bits per code
- Count: 5 codes per account
- OTP: Single-use (removed after use)
notifyId:'authn-recovery-codes'— prefix for the notify template ids:{notifyId}-create,{notifyId}-update,{notifyId}-remove
Codes are a batch, not a credential
Every operation works on the whole set. There is no “add one more”.
create(sub) ──► N codes minted, all verified, all otp
returned once, in the clear, never again
authenticate() ──► one code matches, and is removed on the way out
the rest are untouched -- N-1 remain. two parallel
requests with one code: only one succeeds
update(sub) ──► a fresh batch is minted FIRST, then the old batch
is removed. an interruption leaves the user with
too many codes, never with none
remove(sub) ──► the whole batch goes The ordering in update is deliberate: minting before removing means a failure between the two
is recoverable, where the reverse would lock the user out of their own recovery path.
Codes are stored hashed like any other secret, so the list returned by create is the only
time they exist in readable form. Show them once and tell the user to store them.
API
secret(options)
Recovery code secret configuration.
authenticate(username, secret)
Verify a recovery code. The code is consumed (removed) after successful use.
Rate limiting is your job. Failed attempts are not counted, so nothing stops an attacker from trying codes as fast as you accept requests. A code has 128 bits of entropy, but each try costs an Argon2 hash per remaining code, so limit attempts per account and per IP in your application or gateway.
count(sub)
Count remaining recovery codes for a subject.
list(sub)
List all recovery codes.
create(sub)
Generate a new set of recovery codes.
Returns: Array of plaintext recovery codes (store/display to user immediately — they cannot be retrieved later)
update(sub)
Replace all recovery codes with a new set.
remove(sub, id)
Remove a specific recovery code or all codes.
Post-quantum
Uses only CSPRNG code generation and Argon2id hashing, both post-quantum safe. No migration needed. See the full assessment in Post-quantum.