Topolo Docs Topolo Platform
Open workspace

Regenerate user backup codes

Replace an enabled user complete backup-code set and return new codes once; protected recipient handoff remains separately required.

Outcome

Replace an enabled user complete backup-code set and return new codes once; protected recipient handoff remains separately required.

These examples prove local handler behavior with real isolated JWT/TOTP/envelope/SQL and explicitly synthetic identity/key dependencies.

Before you start

  • Verify pinned identity and exact target authority. Cookie identity precedes Bearer identity; self sub/userId or exact management authority is required. An authenticated denial is not proof of expired OAuth.

  • Use a deliberate private human enrollment/recovery journey. CLI/stdio MCP protects setup secret/token and embedded QR URI, and SDK 0.23.2 protects each backup-code array item separately through a configured protected store. Do not extract protected material, log live codes, use fixture values on real accounts or claim agent credential delivery is proven.

  • Review exact plans/effects before approval. Stored MFA flags, authenticator enrollment, backup-code delivery/use, session state and notifications are separate outcomes. Tokens are actor/target bound and can be consumed before storage fails; already-enabled state and conditional SQL prevent overwriting active MFA.

Discover the target

topolo whoami --json
topolo apps --json
topolo actions get app_topolo_auth.user_mfa.backup_codes.regenerate --detail --json

Resolve the actual authenticated self or authorized managed user and read user_security.get for that exact target. Never retrieve a secret/hash for discovery. Supply current TOTP through the intended private authenticator interface, and pass protected setup-token references unchanged.

Input fields

FieldRequiredMeaning
userIdYesExisting Auth user from credential-scoped discovery. Self identity may use sub or userId; another target requires exact management authority over its organization. Cookie identity precedes Bearer identity for these handlers. A valid administrator credential cannot manage a foreign target.

Effects

  • Replaces all stored backup-code hashes and returns the new set once; repeated calls replace again.

  • Does not change the TOTP secret or prove that the intended recipient received/secured the new codes.

Interpret the response

Requires an MFA-enabled authorized user and replaces the entire stored backup-code set with hashes of ten newly returned codes. Prior codes stop matching. Repeating regeneration creates another replacement set, rather than returning a lost earlier set.

The acknowledgment identifies userId and codes are returned once; sanitized status only reports their presence and cannot retrieve the values. Loss or an unknown response requires reading state and separately approving another replacement, which invalidates any codes already delivered from the prior result.

Raw local examples use fixed synthetic unusable-in-live codes. SDK 0.23.2 preserves the backupCodes array shape while protecting each item separately; local protected-store tests do not prove live CLI/MCP or recipient delivery. Do not deliver a live code set through agent-visible logs. Store and present real recovery material only through the intended private human workflow. Audit is nonfatal; storage does not prove delivery or a backup-code sign-in.

Worked examples

These are complete raw target-handler responses from isolated fixtures, not live or CLI/gateway envelopes. All identifiers, seeds, backup codes and signing keys are synthetic; captured tokens have only a local fixture signature and a fixed already-past lifetime. Never use them for live enrollment. CLI/MCP payloads show the declared request shape and require discovery, private recipient interaction and a reviewed approved plan. SDK 0.23.2 protects each backup-code array item separately through a configured protected store; hosts without one redact sensitive items. Local published-SDK tests do not prove live CLI/MCP or private recipient delivery. A protected setup-token reference must be passed unchanged; no secret extraction or QR reconstruction is authorized by this guide.

Replace the whole backup-code set and return new codes once

Input · payload.json:

{
  "userId": "usr_self"
}

CLI:

topolo actions validate app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --json
topolo actions plan app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --confirm --json

MCP call after validation and plan review:

{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_auth.user_mfa.backup_codes.regenerate",
    "input": {
      "userId": "usr_self"
    },
    "confirm": true
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Backup codes generated successfully",
  "data": {
    "userId": "usr_self",
    "backupCodes": [
      "0000006e",
      "0000006f",
      "00000070",
      "00000071",
      "00000072",
      "00000073",
      "00000074",
      "00000075",
      "00000076",
      "00000077"
    ],
    "warning": "These backup codes replace your previous codes. Store them safely as they will not be shown again."
  },
  "timestamp": "2026-10-02T00:00:00.000Z"
}

Managing administrator regenerates only the selected user code set

Input · payload.json:

{
  "userId": "usr_managed"
}

CLI:

topolo actions validate app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --json
topolo actions plan app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --confirm --json

MCP call after validation and plan review:

{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_auth.user_mfa.backup_codes.regenerate",
    "input": {
      "userId": "usr_managed"
    },
    "confirm": true
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Backup codes generated successfully",
  "data": {
    "userId": "usr_managed",
    "backupCodes": [
      "000000d2",
      "000000d3",
      "000000d4",
      "000000d5",
      "000000d6",
      "000000d7",
      "000000d8",
      "000000d9",
      "000000da",
      "000000db"
    ],
    "warning": "These backup codes replace your previous codes. Store them safely as they will not be shown again."
  },
  "timestamp": "2026-10-02T00:00:00.000Z"
}

Repeated regeneration replaces the previous returned codes again

Input · payload.json:

{
  "userId": "usr_self"
}

CLI:

topolo actions validate app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --json
topolo actions plan app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_mfa.backup_codes.regenerate --data @payload.json --confirm --json

MCP call after validation and plan review:

{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_auth.user_mfa.backup_codes.regenerate",
    "input": {
      "userId": "usr_self"
    },
    "confirm": true
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Backup codes generated successfully",
  "data": {
    "userId": "usr_self",
    "backupCodes": [
      "00000136",
      "00000137",
      "00000138",
      "00000139",
      "0000013a",
      "0000013b",
      "0000013c",
      "0000013d",
      "0000013e",
      "0000013f"
    ],
    "warning": "These backup codes replace your previous codes. Store them safely as they will not be shown again."
  },
  "timestamp": "2026-10-02T00:00:00.000Z"
}

Verify the result

  • Keep the exact userId from the reviewed input/plan and read user_security.get for that same authorized user. Compare mfa_enabled and has_backup_codes; never retrieve or log secret/hash material.

  • Stored status is separate from private authenticator enrollment, normal MFA/backup-code sign-in, physical device entries, session invalidation and notification delivery. Verify the intended human journey independently; synthetic local cryptographic fixtures prove none of these live outcomes.

Errors and recovery

Anonymous MFA operation is refused

Captured local refusal · HTTP 401:

{
  "input": {
    "userId": "usr_self"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Access token required",
      "code": "AUTH_ERROR",
      "details": null,
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Ordinary user cannot manage another MFA target

Captured local refusal · HTTP 401:

{
  "input": {
    "userId": "usr_managed"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Access denied: You can only generate backup codes for yourself",
      "code": "AUTH_ERROR",
      "details": null,
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Organization administrator cannot manage a foreign target

Captured local refusal · HTTP 401:

{
  "input": {
    "userId": "usr_foreign"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Access denied: You can only generate backup codes for yourself",
      "code": "AUTH_ERROR",
      "details": null,
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Missing target user is not provisioned

Captured local refusal · HTTP 404:

{
  "input": {
    "userId": "usr_missing"
  },
  "response": {
    "success": false,
    "error": {
      "message": "User not found",
      "code": "NOT_FOUND",
      "details": null,
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Codes cannot be regenerated before MFA is enabled

Captured local refusal · HTTP 400:

{
  "input": {
    "userId": "usr_self"
  },
  "response": {
    "success": false,
    "error": {
      "message": "MFA must be enabled to generate backup codes",
      "code": "VALIDATION_ERROR",
      "details": {
        "mfa": true
      },
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Published recovery guidance

  • state_conflict (HTTP 409): Read the current resource state, reconcile the intended change, and retry only if still valid.

  • AUTH_ERROR (HTTP 401): Verify pinned identity and cookie/Bearer consistency. Respect target organization authority; an authenticated refusal is not proof of expired OAuth.

  • NOT_FOUND (HTTP 404): Resolve an existing authorized user through published discovery; these actions do not provision users.

  • VALIDATION_ERROR (HTTP 400): Read current target security state. Do not reuse a consumed/expired token, transfer it to another actor, overwrite enabled MFA or infer a backup-code set from status. When disabled after a consumed setup attempt, separately approve a fresh setup; code regeneration requires enabled MFA.

  • SERVER_ERROR (HTTP 500): Preserve the sanitized result/request id and read exact-target state before retry. A verify failure may follow token claim; a successful acknowledgment identifies its user but cannot prove live sign-in or delivery. Do not extract secrets or guess a repair endpoint.

Recovery boundaries

Prior codes are invalidated and cannot be read/restored from sanitized status. After a lost/unknown response inspect state and separately approve another replacement, accounting for codes possibly already delivered. Use SDK 0.23.2 or a compatible newer CLI/MCP with per-item protected references; actual recipient delivery still needs independent private workflow proof.

Discovery and evidence

This record belongs to app_topolo_auth. Local captures use real controller authority, JWT signature/expiry, TOTP, envelope encryption, hash-only backup-code storage and canonical core/session SQL with simulated access-token identity, fixed synthetic credential generation and isolated keys. Lifecycle notification is unconfigured. No live user, authenticator, MFA configuration, code delivery or OAuth state was changed. Stored local state and cryptographic behavior do not prove protected gateway handoff, sign-in, recipient delivery or production completion.