@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.