Skip to main content

Two-Factor Authentication (2FA)

Two-factor authentication adds a second verification step to user login, protecting accounts even if passwords are compromised. Auth Block supports two channels:

ChannelHow It WorksBest For
Email OTP6-digit code sent to user's emailZero-friction setup, no app required
Authenticator App (TOTP)6-digit code from an authenticator appStronger security, works offline

MFA is opt-in per user. Users who don't enable it continue logging in with just their password. No existing flows break.


Setting Up 2FA​

Option A: Email 2FA​

Email 2FA sends a 6-digit code to the user's registered email address during login. No app installation required.

To enable:

  1. Navigate to your account security settings
  2. Select Email as your 2FA method
  3. A verification code is sent to your email
  4. Enter the code to confirm setup
  5. Save your 10 backup codes somewhere safe

Option B: Authenticator App (TOTP)​

TOTP 2FA uses a time-based one-time password generated by an authenticator app on your phone.

Supported apps:

  • Google Authenticator (iOS/Android)
  • Authy (iOS/Android/Desktop)
  • 1Password
  • Bitwarden
  • Microsoft Authenticator

To enable:

  1. Navigate to your account security settings
  2. Select Authenticator App as your 2FA method
  3. Scan the QR code with your authenticator app
    • Can't scan? Use Manual entry — copy the secret key and add it to your app manually
  4. Enter the 6-digit code displayed in your app to verify
  5. Save your 10 backup codes somewhere safe

Backup Codes​

When you enable 2FA, you receive 10 one-time backup codes. Each code can only be used once.

Store these securely — they are your recovery method if you lose access to your email or phone.

  • Print them and keep in a safe place
  • Save them in a password manager
  • Do not store them on the same device as your authenticator app

Disabling 2FA​

To disable 2FA, go to your security settings and confirm with your password. This removes the second factor requirement from your account.


Logging In with 2FA​

With Email OTP​

  1. Enter your email and password as usual
  2. A 6-digit code is sent to your email
  3. Enter the code within 10 minutes
  4. You're logged in

With Authenticator App​

  1. Enter your email and password as usual
  2. Open your authenticator app
  3. Enter the current 6-digit code (codes refresh every 30 seconds)
  4. You're logged in

Using a Backup Code​

If you've lost access to your email or phone:

  1. Enter your email and password as usual
  2. When prompted for a 2FA code, enter one of your backup codes instead
  3. The backup code is consumed (can't be reused)
  4. You're logged in — consider setting up a new 2FA method

Developer Guide: Integrating MFA​

API Endpoints​

All MFA endpoints are under /users/:unique_id/mfa/:

EndpointMethodDescription
/mfa/setupPOSTInitialize MFA setup
/mfa/enablePOSTActivate MFA after verification
/mfa/disablePOSTDeactivate MFA (requires password)
/mfa/verifyPOSTValidate a code or backup code
/mfa/statusGETCheck current MFA state

Setup MFA​

TOTP (Authenticator App)​

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/setup \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{ "channel": "totp" }'

Response:

{
"data": {
"id": "mfa_setup_123",
"type": "mfa_setup",
"attributes": {
"channel": "totp",
"secret": "JBSWY3DPEHPK3PXP",
"qr_code_uri": "otpauth://totp/YourApp:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=YourApp",
"backup_codes": [
"12345678", "23456789", "34567890", "45678901", "56789012",
"67890123", "78901234", "89012345", "90123456", "01234567"
]
}
}
}

Rendering the QR code: Use the qr_code_uri (an otpauth:// URI) to generate a QR code image on your frontend. Libraries like qrcode.js or react-qr-code can render it directly.

Manual entry fallback: Display the secret value for users who can't scan the QR code. They enter it manually in their authenticator app.

Email OTP​

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/setup \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{ "channel": "email" }'

A verification code is sent to the user's email. The response includes backup codes.

Enable MFA​

After the user verifies their setup code:

For TOTP:​

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/enable \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{ "totp_code": "123456" }'

For Email:​

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/enable \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{ "channel": "email" }'

Disable MFA​

Requires the user's password for security:

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/disable \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{ "password": "UserPassword123" }'

Verify a Code​

Validate a TOTP code, email OTP, or backup code:

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/verify \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{ "code": "123456" }'

For backup codes, send the backup code as the code value. It will be consumed on successful verification.

Check MFA Status​

curl -X GET https://auth.api.us.23blocks.com/users/usr_abc123/mfa/status \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key"

Response:

{
"data": {
"id": "usr_abc123",
"type": "mfa_status",
"attributes": {
"mfa_enabled": true,
"mfa_channel": "totp",
"backup_codes_remaining": 9
}
}
}

Handling MFA in Login Flow​

When a user with MFA enabled signs in, the response includes mfa_required:

Step 1: Normal sign-in attempt

curl -X POST https://auth.api.us.23blocks.com/auth/sign_in \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123"
}'

Response when MFA is required:

{
"data": {
"id": "usr_abc123",
"type": "user",
"attributes": {
"unique_id": "usr_abc123",
"mfa_required": true,
"mfa_channel": "totp"
}
}
}

Step 2: Submit MFA code

curl -X POST https://auth.api.us.23blocks.com/auth/sign_in \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123",
"mfa_code": "123456"
}'

This returns the full user object with JWT on success.

Same flow applies to passwordless verify (POST /auth/passwordless/verify) — if the user has MFA enabled, they must provide the MFA code alongside the OTP.

User Serializer Fields​

The user object now includes MFA fields:

FieldTypeDescription
mfa_enabledbooleanWhether MFA is active
mfa_channelstring | null"email", "totp", or null if not enabled

UX Best Practices​

Backup code recovery:

  • Show backup codes on a dedicated screen after setup
  • Allow the user to copy or download them
  • Remind users who haven't saved codes
  • Display remaining backup code count in security settings

QR code rendering:

  • Use the qr_code_uri from the setup response — it's a standard otpauth:// URI
  • Always show the manual secret as a fallback below the QR code
  • Label the entry clearly so users can identify it in their authenticator app

Channel selection:

  • Present Email as the simpler option (no app required)
  • Present TOTP as the stronger option (works offline, not vulnerable to email compromise)
  • Let users switch channels by disabling and re-enabling MFA

Tenant Admin Guide​

MFA Adoption​

MFA is opt-in per user. There is no tenant-wide enforcement setting at this time. Administrators can check MFA adoption across their user base by querying user records for the mfa_enabled field.

Security Recommendations​

User RoleRecommendation
Admin / OwnerStrongly encourage TOTP (authenticator app)
Regular usersEncourage Email OTP as a low-friction starting point
API-only accountsMFA not applicable — use service tokens instead
High-security rolesRequire TOTP and verify backup codes are saved

Monitoring​

  • Track mfa_enabled and mfa_channel fields across your user base
  • Monitor backup code usage — high usage may indicate users losing access to their primary 2FA method
  • Audit MFA setup/disable events for suspicious patterns

Use This Block with AI Agents​

This block ships an official Claude Code plugin from the public 23blocks marketplace (19 plugins, 205 skills). Your agent gets full working knowledge of this API — endpoints, identity registration, and conventions.

# one-time: add the 23blocks marketplace
claude plugin marketplace add https://github.com/23blocks-OS/ai-agents

# install this block's plugin
claude plugin install auth-block

Configure BLOCKS_API_URL, BLOCKS_API_KEY, and BLOCKS_AUTH_TOKEN. Register identity first: each block is autonomous — register the user with this block's identity endpoint before private calls (only user_unique_id is required; email/phone are optional notification-routing fields).

Full reference: AI Agents & Claude Code Plugins · github.com/23blocks-OS/ai-agents