Mint a fresh set of recovery codes
Recovery codes are the fallback that gets you back in when your passkey is unavailable. You can mint a fresh set yourself, and there are two things to understand before you do, because both are irreversible in the moment.
Regenerating destroys the old set, and shows the new one once
Minting a fresh set invalidates every previous code for your address immediately. There is no overlap period and no way to keep the old set working alongside the new one.
The new codes are returned once, for one-time display. They are not stored in a form that can be shown again and there is no route that will return them a second time.
The console shows them in the Save your new recovery codes view, with Copy and Download .txt under the codes. You cannot dismiss this view. Escape and a click outside it do nothing, and it has no close button. Continue is the only way out, and it stays disabled until you tick “I have saved my recovery codes”.
Tick that box only when you hold a copy. If you continue without one, the outcome is not “look them up later”: you have invalidated your old codes and hold none. Put the new codes where you keep your other break-glass material, not where you keep your passwords.
You can only regenerate your own
The route identifies you the same way every other authenticated route does, then scopes the regeneration to your own verified email address. There is no parameter for whose codes to mint, so an owner cannot regenerate a colleague’s set on their behalf, and nobody can regenerate yours.
If a colleague has lost both their passkey and their codes, this route is not the answer for them; that is an account-recovery conversation, not a regeneration.
A break-glass token cannot regenerate a set
Signing in with the bare break-glass token and asking for fresh recovery codes is refused, and the reason is worth stating because the refusal looks arbitrary.
Recovery codes are a per-user credential, scoped to an email address. The break-glass token is not a per-email identity: it has no address to scope a set to. Beyond that, the token is the credential you are meant to be disposing of in a recovery, not one that holds recovery codes of its own.
The refusal says so in the response: recovery codes are per-user, so sign in as a user, by passkey or through Cloudflare Access, to regenerate.
Every way the request is refused
Not signed in. A 401. Nothing about your codes changed.
Signed in with no user identity. A 403 with the per-user explanation above. This is the break-glass token case.
A fresh identity check is needed. Regenerating is a sensitive action, so it asks for step-up re-authentication first. Approve the prompt and it proceeds. A session that starts with a recovery code does not satisfy step-up; step-up needs a passkey, either an existing passkey or one enrolled after recovery. See step-up re-authentication.
The request did not come from the console. A 403 on the origin check. A session-cookie caller must send an Origin that matches CONSOLE_ORIGIN. A Cloudflare Access caller must match it too whenever its request carries an Origin header. An Access request with no Origin skips the check (handleRegenerate, engine/src/admin/router-auth-flow.ts). Every other mutating route takes the same rule.
Too many attempts. The authentication rate limit applies here as it does to signing in, so a burst of attempts is throttled rather than served.
Your address is no longer on the account’s roster. A 403. If your role grant has been removed and you are on a passkey session, the engine will not mint you a fresh supply of codes. This is the one refusal that can surprise a person who signed in successfully a moment earlier, because a recovery-code sign-in mints a session that the sign-in checks accept, although it must still present a fresh passkey assertion at the step-up check. The codes you already hold still sign you in, and an owner can restore the grant. A caller whose authority comes from an identity-provider group claim rather than a role row is not affected, because that authority does not appear on the roster and the check applies only to the passkey method.
In each case no codes are minted and none are invalidated. A refused regeneration leaves your existing set working, which is the safe direction: the failure mode to avoid is one that destroys the old set without delivering a new one.
A successful regeneration signs you out elsewhere
Regenerating rotates a sign-in factor, which is something you often do after a suspected compromise, so the engine also bumps your address’s session epoch. Every session issued for your address before the rotation, including ones on your other devices, fails on its next request. Enrolling your first set does not do this; only an explicit regeneration does.
Capture the new codes before you go anywhere else, because the sign-out lands on the same address you are reading them on.
Where this fits
- Session management covers the sessions a passkey sign-in creates.
- Step-up re-authentication covers the fresh-proof requirement this route sits behind.
- Offboarding and exit covers what to do with a departing user’s credentials, which is a different question from regenerating your own.
- The key ceremony and recovery kit covers the break-glass material these codes sit alongside.
Last updated .