---
title: "Give recovery codes with the first second · Agent Wranglers"
url: https://agentwranglers.se/playbook/accounts/second-factors-and-recovery/recovery-codes
updated: 2026-10-20
licence: "All rights reserved"
---

# Give recovery codes with the first second factor

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Second factors and recovery](https://agentwranglers.se/playbook/accounts/second-factors-and-recovery)
- Rule: When someone turns on a second factor, give them 10 single-use recovery codes of at least 64 random bits each, and store only their hashes.
- How: Make each code from a secure random source, such as 13 characters of base32 for 65 bits. NIST SP 800-63B-4 section 4.2.1.1 sets the 64-bit minimum for saved recovery codes. Show the codes once, with buttons to copy, download and print. Hash each one like a password and mark it used on success. A new set cancels the old one. Email a notice whenever a code is used. Warn in the app when 2 or fewer are left.
- Check: Sign in with one recovery code, then try it again. The second use fails, and the notice email arrived. No code appears in plain text in the database.

Example:

```js
import { randomInt } from 'node:crypto';

const CROCKFORD_BASE32 = '0123456789abcdefghjkmnpqrstvwxyz';
const CODE_LENGTH = 13; // 13 characters of 5 bits each give 65 bits
const CODE_COUNT = 10;

export const newRecoveryCodes = () => Array.from({ length: CODE_COUNT }, () =>
  Array.from({ length: CODE_LENGTH }, () => CROCKFORD_BASE32[randomInt(CROCKFORD_BASE32.length)]).join(''));
```

```python
import secrets

CROCKFORD_BASE32 = "0123456789abcdefghjkmnpqrstvwxyz"
CODE_LENGTH = 13  # 13 characters of 5 bits each give 65 bits
CODE_COUNT = 10

def new_recovery_codes() -> list[str]:
    return ["".join(secrets.choice(CROCKFORD_BASE32) for _ in range(CODE_LENGTH)) for _ in range(CODE_COUNT)]
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers accounts playbook: https://agentwranglers.se/playbook/accounts/second-factors-and-recovery/recovery-codes`.

- Previous: [Confirm a second factor before turning it on](https://agentwranglers.se/playbook/accounts/second-factors-and-recovery/mfa-enrolment)
- Next: [Ask everyone to keep two ways in](https://agentwranglers.se/playbook/accounts/second-factors-and-recovery/two-authenticators)
- [Second factors and recovery](https://agentwranglers.se/playbook/accounts/second-factors-and-recovery)
