Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/zitadel/zitadel/llms.txt

Use this file to discover all available pages before exploring further.

Multi-Factor Authentication (MFA) adds an additional layer of security by requiring users to provide two or more verification factors to access their accounts. ZITADEL supports multiple MFA methods including OTP, U2F, SMS, and email-based verification.

MFA Methods

ZITADEL supports the following multi-factor authentication methods:

Time-based One-Time Password (TOTP)

TOTP generates time-based codes using authenticator apps like:
  • Google Authenticator
  • Microsoft Authenticator
  • Authy
  • 1Password
  • Any RFC 6238-compliant authenticator
Security Level: Second Factor Implementation: RFC 6238 standard TOTP algorithm

Universal 2nd Factor (U2F)

Hardware security keys using the FIDO U2F standard:
  • YubiKey
  • Google Titan Security Key
  • Other FIDO-compliant security keys
Security Level: Second Factor or Multi-Factor Implementation: WebAuthn/FIDO2 protocol

OTP via SMS

One-time passwords delivered via SMS text message to the user’s registered phone number. Security Level: Second Factor Implementation: Requires SMS provider configuration (Twilio or custom webhook)
SMS-based OTP is less secure than TOTP or U2F due to potential SIM swapping attacks. Use for convenience but consider stronger methods for high-security scenarios.

OTP via Email

One-time passwords sent to the user’s registered email address. Security Level: Second Factor Implementation: Uses configured SMTP or email provider

MFA Configuration

Enabling MFA Methods

Configure which MFA methods are available through the Login Policy.

Via Console

1

Navigate to Login Policy

Go to Instance/Organization Settings > Login Policy
2

Configure Second Factors

In the Second Factors section, select available methods:
  • TOTP (Time-based OTP)
  • OTP Email
  • OTP SMS
3

Configure Multi-Factors

In the Multi-Factors section, add additional factor options:
  • U2F (Universal 2nd Factor)
4

Set MFA Policy

Choose MFA enforcement:
  • Optional: Users can enable MFA voluntarily
  • Required: All users must configure MFA (Force MFA)
  • Required for Local Only: Only local accounts require MFA, not federated users

Via API

# Add TOTP as a second factor
curl -X POST https://$ZITADEL_DOMAIN/v2/settings/login_policy/second_factors \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "SECOND_FACTOR_TYPE_OTP"
  }'

# Add U2F as a multi-factor
curl -X POST https://$ZITADEL_DOMAIN/v2/settings/login_policy/multi_factors \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "MULTI_FACTOR_TYPE_U2F"
  }'

# Enable Force MFA
curl -X PUT https://$ZITADEL_DOMAIN/v2/settings/login_policy \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "forceMfa": true
  }'

MFA Enforcement Modes

ForceMFA: When enabled, all users must configure at least one MFA method before they can complete authentication. ForceMFALocalOnly: When enabled, only users authenticating with local credentials (username/password) must use MFA. Users authenticating via external identity providers are exempt.
// From internal/domain/policy_login.go
type LoginPolicy struct {
    ForceMFA          bool
    ForceMFALocalOnly bool
    SecondFactors     []SecondFactorType
    MultiFactors      []MultiFactorType
    // ...
}

Setting Up MFA Methods

TOTP Setup

1

User Initiates Setup

User navigates to account settings and selects “Add Authenticator App”
2

QR Code Generation

ZITADEL generates a QR code containing the TOTP secret
3

Scan with Authenticator

User scans the QR code with their authenticator app
4

Verify Setup

User enters the current TOTP code to verify the setup is working
5

Save Recovery Codes

ZITADEL provides recovery codes for account recovery if the device is lost

TOTP Configuration

The TOTP configuration is managed through MultifactorConfigs:
// From internal/domain/mfa.go
type MultifactorConfigs struct {
    OTP           OTPConfig
    RecoveryCodes RecoveryCodesConfig
}

type OTPConfig struct {
    Issuer    string  // Displayed in authenticator app
    CryptoMFA crypto.EncryptionAlgorithm
}

U2F/WebAuthn Setup

1

User Initiates Registration

User selects “Add Security Key” in account settings
2

Insert Security Key

User inserts their U2F security key or prepares their device authenticator
3

Trigger Registration

Browser prompts for user interaction (touch security key button)
4

Complete Registration

ZITADEL stores the public key and associates it with the user account
5

Name the Key

User provides a friendly name for the security key (e.g., “YubiKey 5C”)

OTP SMS Setup

1

Configure SMS Provider

First, configure an SMS provider in ZITADEL (Twilio or custom webhook)
2

User Adds Phone Number

User enters their phone number in account settings
3

Verify Phone Number

ZITADEL sends a verification code via SMS
4

Complete Verification

User enters the code to verify phone ownership
5

Enable OTP SMS

OTP SMS is now available as an MFA method for the user

API Setup

# Add OTP SMS to a user
curl -X POST https://$ZITADEL_DOMAIN/v2/users/{userId}/otp_sms \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json"

# Remove OTP SMS
curl -X DELETE https://$ZITADEL_DOMAIN/v2/users/{userId}/otp_sms \
  -H "Authorization: Bearer $ACCESS_TOKEN"

OTP Email Setup

1

Verify Email Address

User must have a verified email address on their account
2

Enable OTP Email

User enables OTP Email in account security settings
3

Test Delivery

ZITADEL sends a test code to verify email delivery
4

Complete Setup

User enters the test code to confirm setup

API Setup

# Add OTP Email to a user
curl -X POST https://$ZITADEL_DOMAIN/v2/users/{userId}/otp_email \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json"

# Remove OTP Email
curl -X DELETE https://$ZITADEL_DOMAIN/v2/users/{userId}/otp_email \
  -H "Authorization: Bearer $ACCESS_TOKEN"

MFA Authentication Flow

When MFA is required, the authentication flow includes an additional verification step:
1

Primary Authentication

User provides primary credentials (username/password or passkey)
2

MFA Challenge

ZITADEL prompts for second factor based on user’s registered methods
3

User Selects Method

If multiple MFA methods are registered, user chooses which one to use
4

Provide Second Factor

User provides the second factor (TOTP code, U2F key, SMS code, etc.)
5

Verification

ZITADEL verifies the second factor
6

Session Creation

Successful MFA grants access and creates an authenticated session

MFA State Management

// From internal/domain/mfa.go
type MFAState int32

const (
    MFAStateUnspecified MFAState = iota
    MFAStateNotReady    // MFA setup initiated but not completed
    MFAStateReady       // MFA fully configured and active
    MFAStateRemoved     // MFA was removed from account
)

Recovery Codes

Recovery codes provide a backup authentication method if users lose access to their MFA devices.

Generating Recovery Codes

When users enable MFA, ZITADEL generates a set of single-use recovery codes.
// From internal/domain/mfa.go
type RecoveryCodesConfig struct {
    MaxCount   int                // Number of codes to generate
    Format     RecoveryCodeFormat // Format of codes
    Length     int                // Length of each code
    WithHyphen bool               // Include hyphens for readability
}

const (
    RecoveryCodeFormatUUID         RecoveryCodeFormat = "uuid"
    RecoveryCodeFormatAlphanumeric RecoveryCodeFormat = "alphanumeric"
)

Using Recovery Codes

1

Select Recovery Option

During MFA prompt, user selects “Use recovery code” option
2

Enter Code

User enters one of their saved recovery codes
3

Code Validation

ZITADEL validates and invalidates the used recovery code
4

Access Granted

User gains access and should set up MFA again or generate new recovery codes
Recovery codes are single-use. Once all recovery codes are consumed, users must generate new ones or risk account lockout if they lose their MFA device.

MFA Lifetime Settings

Control how long MFA verification remains valid:

Second Factor Check Lifetime

curl -X PUT https://$ZITADEL_DOMAIN/v2/settings/login_policy \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "secondFactorCheckLifetime": "43200s"  // 12 hours
  }'

Multi-Factor Check Lifetime

curl -X PUT https://$ZITADEL_DOMAIN/v2/settings/login_policy \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "multiFactorCheckLifetime": "43200s"  // 12 hours
  }'

MFA Init Skip Lifetime

Allow users to skip MFA setup for a period:
curl -X PUT https://$ZITADEL_DOMAIN/v2/settings/login_policy \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "mfaInitSkipLifetime": "2592000s"  // 30 days
  }'

Best Practices

Enforce MFA for Sensitive Operations: Always require MFA for privileged accounts (administrators, service accounts with elevated permissions).
Provide Multiple Options: Enable multiple MFA methods to accommodate different user preferences and scenarios.
Educate Users: Provide clear instructions and support documentation for MFA setup and usage.
Recovery Planning: Ensure users save recovery codes and understand the recovery process before they need it.
SMS Limitations: While convenient, SMS-based OTP is vulnerable to SIM swapping. For high-security applications, prefer TOTP or U2F.

SMS Provider Configuration

To use OTP SMS, configure an SMS provider:

Twilio Configuration

Notifications:
  Providers:
    Twilio:
      SID: "your-twilio-account-sid"
      Token: "your-twilio-auth-token"
      SenderNumber: "+1234567890"

Custom SMS Webhook

Alternatively, configure a custom webhook for SMS delivery:
Notifications:
  Providers:
    Webhook:
      Enabled: true
      URL: "https://your-sms-provider.com/send"
      Headers:
        Authorization: "Bearer your-token"

Troubleshooting

MFA Setup Fails

Check time synchronization: TOTP requires accurate system time (use NTP) Verify QR code: Ensure the QR code is scanned correctly Browser compatibility: Confirm WebAuthn support for U2F setup

MFA Verification Fails

Time drift: TOTP codes expire every 30 seconds; ensure timely entry Used recovery code: Recovery codes are single-use only SMS not received: Check SMS provider configuration and phone number validity U2F timeout: User must interact with security key within the timeout period

Account Lockout

Use recovery codes: Enter a saved recovery code to regain access Administrator intervention: Admins can disable MFA for locked-out users Account recovery flow: Implement proper account recovery procedures

API Reference

Key MFA-related API endpoints:

Add TOTP

POST /v2/users/{userId}/totp

Verify TOTP

POST /v2/users/{userId}/totp/verify

Add OTP SMS

POST /v2/users/{userId}/otp_sms

Add OTP Email

POST /v2/users/{userId}/otp_email

Register U2F Token

POST /v2/users/{userId}/u2f

List User’s MFA Methods

GET /v2/users/{userId}/authentication_methods
See the User Service API for complete documentation.