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