Skip to main content

POST /v1/auth/mfa/setup

Begin TOTP enrollment. Generates a fresh secret, persists it on the user record (marked not-yet-enabled), and returns it plus a QR code PNG for the user to scan into an authenticator app.

::: tip Auth Required: cookie or Bearer. :::

Request

POST /v1/auth/mfa/setup

HeaderRequiredNotes
Cookie: identsphere_at=... OR Authorization: Bearer ...yes

No request body.

Response

200 OK

{
"secret": "JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP",
"qr_code_base64": "iVBORw0KGgoAAAANSUhEUgAA..."
}
FieldTypeNotes
secretstringBase32 (RFC 4648, no padding), 20 bytes of entropy. Suitable for manual entry into an authenticator app.
qr_code_base64stringPNG image of an otpauth:// URI, base64-encoded. Render with <img src="data:image/png;base64,...">.

Error responses

StatusCodeWhen
401authentication_requiredNo valid auth credential.
404not_foundUser no longer exists.
409conflictMFA is already enabled — use /disable first if rotating.
500internal_errorTOTP build / QR generation failure.

Example: curl

curl -X POST https://auth.example.com/v1/auth/mfa/setup -b cookies.txt

Example: TypeScript (@identsphere/react)

import { useMfaSetup } from '@identsphere/react';

function MfaEnrollStep1() {
const setup = useMfaSetup();
return (
<button
onClick={async () => {
const { qr_code_base64, secret } = await setup.mutateAsync();
setQr(qr_code_base64);
setSecret(secret);
}}
>
Begin MFA enrollment
</button>
);
}

Notes

  • The secret is persisted immediately, but mfa_enabled stays false until the user proves they scanned it correctly via POST /v1/auth/mfa/enable.
  • Calling /setup more than once before /enable is allowed — each call generates a fresh secret and overwrites the prior pending one.
  • The TOTP parameters are RFC 6238 defaults: SHA-1, 6 digits, 30-second window. These match what authenticator apps (Google Authenticator, Authy, 1Password, Bitwarden, etc.) expect by default.
  • The issuer baked into the QR-code URI is AppConfig::app_name, which is what the authenticator displays as the account label.