Skip to content

Independent MFA

Last updated View as MarkdownAgent setup

Independent multi-factor authentication (MFA) allows you to enforce MFA requirements directly in Access without relying on your identity provider (IdP). Users authenticate with their IdP as usual, and Access prompts for an additional authentication method before granting access to the application.

Because you can configure MFA at the application and policy level, you can enforce stricter authentication methods like hardware security keys on sensitive applications without requiring them across your entire organization. This allows you to add additional security where it matters most while avoiding MFA fatigue for your broader user population.

Supported MFA methods

MFA method Description
Authenticator application Time-based one-time passwords (TOTP) generated by apps such as Google Authenticator, Microsoft Authenticator, or Authy. Access supports one TOTP authenticator per user at a time.
Security key Hardware security keys that support the WebAuthn standard. Users can enroll multiple security keys.
Biometrics Built-in device authenticators that use WebAuthn, including Apple Touch ID, Apple Face ID, and Windows Hello. Users can enroll multiple biometrics.
Personal Identity Verification (PIV) key (infrastructure apps only) YubiKey PIV keys used for public key authentication during SSH connections. Requires YubiKey firmware 4.3 or later. This method is only available for infrastructure applications. Users can enroll multiple PIV keys.
FIDO2 key (infrastructure apps only) YubiKey FIDO2 keys used for public key authentication during SSH connections. This method is only available for infrastructure applications and is separate from the browser-based WebAuthn security key method.

Turn on independent MFA

Before you can enforce independent MFA on applications and policies, you must turn on independent MFA at the organization level.

  1. In the Cloudflare dashboard, go to Zero Trust > Access controls > Access settings.

  2. Under Allow multi-factor authentication (MFA), select the MFA methods you want to allow in your organization.

  3. Set an Authentication duration. This determines how long a user can log in to Access without being prompted for MFA again. If the user does not have an active MFA session for the required authenticator method, they must complete MFA in addition to IdP authentication.

  4. (Optional) To avoid double prompting a user for MFA, you can enable Use identity provider MFA. This will check the AMR value passed from the identity provider at the time of authentication, if that AMR value passes an allowed MFA method, the user will not be prompted for MFA for the duration configured.

  5. (Optional) To apply your MFA methods and authentication duration to all Access applications, select Apply global MFA settings by default. You can override the global MFA settings for individual applications and policies.

  6. Select Save.

  1. Get your existing Zero Trust organization configuration:

    Required API token permissions

    At least one of the following token permissions is required:
    • Access: Organizations, Identity Providers, and Groups Revoke
    • Access: Organizations, Identity Providers, and Groups Write
    • Access: Organizations, Identity Providers, and Groups Read
    Get your Zero Trust organizationbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations" \
    	--request GET \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  2. Send a PUT request to update your organization's MFA settings. To avoid overwriting your existing configuration, the PUT request body should contain all fields returned by the previous GET request.

    Required API token permissions

    At least one of the following token permissions is required:
    • Access: Organizations, Identity Providers, and Groups Write
    Update your Zero Trust organizationbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations" \
    	--request PUT \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    	--json '{
    		"auth_domain": "your-team-name.cloudflareaccess.com",
    		"name": "Your Team Name",
    		"mfa_config": {
    				"allowed_authenticators": [
    						"totp",
    						"biometrics",
    						"security_key"
    				],
    				"session_duration": "24h"
    		},
    		"mfa_required_for_all_apps": false
    	}'

    Set allowed_authenticators to an array containing one or more of:

    • totp — Authenticator application (time-based one-time passwords).
    • biometrics — Biometrics (Touch ID, Face ID, Windows Hello).
    • security_key — Security keys (hardware keys that support WebAuthn).
    • piv_key — PIV keys (YubiKeys).
    • ssh_fido2_key — FIDO2 keys for SSH connections to infrastructure applications.

    piv_key and ssh_fido2_key apply only to SSH connections to infrastructure applications. If allowed at the organization level, these MFA methods will only apply to infrastructure applications. They will not be available for other application types.

    Set session_duration to a duration string (for example, 30m, 1h, 24h). To require MFA on every access, use 0m.

After you turn on independent MFA, users can enroll authenticators through the App Launcher.

Configure PIV key requirements

If you plan to use PIV keys for MFA for infrastructure applications, configure the PIV key requirements in your organization's Access settings. These requirements determine which PIV keys users can enroll.

  1. In the Cloudflare dashboard, go to Zero Trust > Access controls > Access settings.

  2. Under Allow multi-factor authentication (MFA), turn on the "Personal Identity Verification (PIV) key" authenticator.

  3. Configure the following settings:

    Setting Description Options
    Key type The SSH key algorithm ECDSA, Ed25519, RSA
    Key size The key length in bits ECDSA: 256, 384, 521. RSA: 2048, 3072, 4096
    PIN policy When the user must enter their PIV PIN never, once (once per session), always (every use)
    Touch policy When the user must touch the hardware key never, always (every use), cached (cached for 15 seconds)
    Require FIPS Require the PIV key to be on a FIPS-validated device true, false
  4. Select Save.

Restrict authenticators by AAGUID

An AAGUID (Authenticator Attestation GUID) is a 128-bit identifier that indicates the make and model of a WebAuthn authenticator. By restricting enrollment to a specific set of AAGUIDs, you can require that users only enroll approved hardware, such as FIPS-validated security keys or company-issued devices.

Access checks the AAGUID when a user registers an authenticator. Because enrollment applies to the entire organization, you configure AAGUID restrictions at the organization level.

For FIDO2 keys, Access also checks the AAGUID each time the user connects to an infrastructure application. If you remove a FIDO2 key from the allowed list, that key stops working even if the user enrolled it earlier.

PIV keys do not present an AAGUID, so these restrictions do not apply to them.

When required_aaguids is unset, Access does not enforce AAGUID restrictions.

1. Create an AAGUID list

AAGUIDs are managed using Lists. Create a list of type AAGUID, then reference the list in your organization's MFA configuration.

  1. In the Cloudflare dashboard, go to Zero Trust > Resources > Lists.
  2. Select Create new list.
  3. Enter a List name (for example, Approved security keys) and an optional description.
  4. Set List type to MFA AAGUIDs.
  5. Add one or more AAGUID entries:
    • To add predefined AAGUIDs, select authenticators from the Known authenticators list.
    • To add a custom AAGUID, fill out the following fields:
      • MFA AAGUIDs — The AAGUID of the authenticator, in 32-character hexadecimal format without dashes (for example, 8c39ee867f9a4a959ba3f6b097e5c2ee).
      • Description — An optional label such as the authenticator's name and model.
  6. Select Save.

Send a POST request to create the list:

Create Zero Trust listbash
curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/lists" \
	--request POST \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
	--json '{
		"name": "Approved security keys",
		"description": "AAGUIDs for MFA enrollment",
		"type": "AAGUID",
		"items": [
				{
						"value": "8c39ee867f9a4a959ba3f6b097e5c2ee",
						"description": "YubiKey Bio Series - FIDO Edition (Enterprise Profile)"
				}
		]
	}'

The response contains an id (UUID) for the list. Use this ID when you assign the list to your organization's MFA configuration.

2. Assign an AAGUID list to your organization

  1. In the Cloudflare dashboard, go to Zero Trust > Access controls > Access settings.
  2. Under Allow multi-factor authentication (MFA), go to Limit MFA to specific authentication methods.
  3. Select an existing AAGUID list.
  4. Select Save.

After you save, only authenticators whose AAGUIDs appear in the list can be enrolled. Users with previously enrolled security keys or biometrics outside the list can continue to use them until they are deleted by an administrator. A previously enrolled FIDO2 key outside the list stops working on the next connection. To remove the restriction, unset the AAGUID list.

  1. Get your existing Zero Trust organization configuration:

    Required API token permissions

    At least one of the following token permissions is required:
    • Access: Organizations, Identity Providers, and Groups Revoke
    • Access: Organizations, Identity Providers, and Groups Write
    • Access: Organizations, Identity Providers, and Groups Read
    Get your Zero Trust organizationbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations" \
    	--request GET \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  2. Send a PUT request to assign the list. To avoid overwriting your existing configuration, the PUT request body should contain all fields returned by the previous GET request. Set mfa_config.required_aaguids to the ID of your AAGUID list.

    Required API token permissions

    At least one of the following token permissions is required:
    • Access: Organizations, Identity Providers, and Groups Write
    Update your Zero Trust organizationbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations" \
    	--request PUT \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    	--json '{
    		"auth_domain": "your-team-name.cloudflareaccess.com",
    		"name": "Your Team Name",
    		"mfa_config": {
    				"allowed_authenticators": [
    						"security_key",
    						"totp",
    						"biometrics"
    				],
    				"session_duration": "24h",
    				"required_aaguids": "05ddacda-5131-41ab-9eeb-6763f8dce3be"
    		}
    	}'

    To remove the restriction, set required_aaguids to null.

Use identity provider MFA

If your identity provider already prompts users for MFA, you can configure Access to accept that MFA instead of prompting again. Access checks the Authentication Method Reference (AMR) claim returned by the IdP, as defined in RFC 8176. If the AMR value matches an allowed authenticator type for the application or policy, Access skips the independent MFA prompt.

Supported AMR values

AMR value Matches Access authenticator type Description
hwk Security key Proof-of-possession of a hardware key
swk Security key Proof-of-possession of a software key
otp Authenticator application One-time password
face Biometrics Facial recognition
fpt Biometrics Fingerprint
iris Biometrics Iris scan
retina Biometrics Retina scan
vbm Biometrics Voice biometric

Access ignores AMR values that do not map to a supported authenticator type (for example, pwd, sms, tel, geo, kba, sc, pin, user, mca, rba, wia).

Turn on AMR matching

  1. In the Cloudflare dashboard, go to Zero Trust > Access controls > Access settings.
  2. Under Allow multi-factor authentication (MFA), turn on Use identity provider MFA.
  3. Under Authentication Method Reference (AMR) matching duration, set how long a successful IdP MFA remains valid. During this period, users can log in to Access without an additional MFA prompt. You can set a custom duration (default 24 hours) or check for a valid AMR value on every login.
  4. Select Save.
  1. Get your existing Zero Trust organization configuration:

    Required API token permissions

    At least one of the following token permissions is required:
    • Access: Organizations, Identity Providers, and Groups Revoke
    • Access: Organizations, Identity Providers, and Groups Write
    • Access: Organizations, Identity Providers, and Groups Read
    Get your Zero Trust organizationbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations" \
    	--request GET \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  2. Send a PUT request to update your organization's AMR matching settings. To avoid overwriting your existing configuration, the PUT request body should contain all fields returned by the previous GET request.

    Required API token permissions

    At least one of the following token permissions is required:
    • Access: Organizations, Identity Providers, and Groups Write
    Update your Zero Trust organizationbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations" \
    	--request PUT \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    	--json '{
    		"auth_domain": "your-team-name.cloudflareaccess.com",
    		"name": "Your Team Name",
    		"mfa_config": {
    				"allowed_authenticators": [
    						"totp",
    						"biometrics",
    						"security_key"
    				],
    				"session_duration": "24h",
    				"amr_matching_enabled": true,
    				"amr_session_duration": "1h"
    		}
    	}'

When AMR matching is skipped

Access does not apply AMR matching in the following cases:

  • The IdP does not return an amr claim.
  • The IdP returns only AMR values that do not map to an allowed authenticator type for the application or policy.
  • The user's AMR matching session has expired because they last performed MFA via their IdP longer ago than the configured AMR matching duration.

In these cases, Access falls back to checking for existing MFA sessions. If there are no valid MFA sessions, Access prompts the user to complete independent MFA.

Turn off independent MFA

To turn off independent MFA for the organization:

  1. In the Cloudflare dashboard, go to Zero Trust > Access controls > Access settings.
  2. Under Allow multi-factor authentication (MFA), turn off Apply global MFA settings by default.
  3. Turn off all MFA methods (Biometrics, Security key, and Authenticator application).

If you get an error updating MFA settings, ensure that you have removed custom MFA settings from all applications and policies.

  1. Get your existing Zero Trust organization configuration:

    Required API token permissions

    At least one of the following token permissions is required:
    • Access: Organizations, Identity Providers, and Groups Revoke
    • Access: Organizations, Identity Providers, and Groups Write
    • Access: Organizations, Identity Providers, and Groups Read
    Get your Zero Trust organizationbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations" \
    	--request GET \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  2. Send a PUT request with an empty allowed_authenticators array. To avoid overwriting your existing configuration, the PUT request body should contain all fields returned by the previous GET request.

    Required API token permissions

    At least one of the following token permissions is required:
    • Access: Organizations, Identity Providers, and Groups Write
    Update your Zero Trust organizationbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/organizations" \
    	--request PUT \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    	--json '{
    		"auth_domain": "your-team-name.cloudflareaccess.com",
    		"name": "Your Team Name",
    		"mfa_config": {
    				"allowed_authenticators": []
    		}
    	}'

Enroll authenticators

Users enroll authenticators through the App Launcher.

If a user already has at least one authenticator enrolled, Access requires them to verify with an existing MFA method before they can add a new authenticator.

To enroll an authenticator:

  1. Go to your organization's App Launcher at <your-team-name>.cloudflareaccess.com.

  2. Log in with your identity provider or with a one-time PIN (OTP).

  3. Go to Account > MFA devices > Add an MFA device.

  4. If you already have an MFA device enrolled, complete the MFA verification prompt.

  5. Select the authenticator type you want to enroll and follow the on-screen instructions.

    Authenticator application

    1. Select Authenticator application.
    2. Scan the QR code with your authenticator app (for example, Google Authenticator, Microsoft Authenticator, or Authy). Alternatively, you can manually enter the setup key into your authenticator app. Use SHA1 as the hash function and set the time-step size to 30 seconds.
    3. Enter the 6-digit time-based one-time password (TOTP) generated by your authenticator app to verify enrollment.

    Security key

    1. Select Security key.
    2. When your browser prompts you, insert your security key and follow the on-screen instructions.
    3. After your browser confirms the registration, the security key is enrolled.

    You can enroll multiple security keys for backup purposes.

    Biometrics

    1. Select Biometrics > Register biometrics.
    2. You will be prompted to enroll with an authenticator type that is available on your device (for example, Add macOS Touch ID or Add Windows Hello).
    3. After your browser confirms the registration, the platform authenticator is enrolled.

    PIV key (infrastructure applications only)

    PIV key enrollment requires additional client-side setup and is only used for MFA with infrastructure applications. For full instructions, refer to Enroll a PIV key for infrastructure apps.

    FIDO2 key (infrastructure applications only)

    FIDO2 key enrollment requires additional client-side setup and is only used for MFA with infrastructure applications. This method is separate from browser-based security key enrollment. For full instructions, refer to Enroll a FIDO2 key for infrastructure apps.

You can now use these authenticators to log in to your organization's applications.

Enroll a FIDO2 key for infrastructure apps

Before users can enroll, turn on the FIDO2 key authenticator in your organization's global MFA settings.

The App Launcher generates the enrollment command for your account. Do not construct the enrollment command manually.

  1. Go to your organization's App Launcher at <your-team-name>.cloudflareaccess.com.
  2. Log in with your identity provider or a one-time PIN (OTP).
  3. Go to Account > MFA devices > Add an MFA device > FIDO2 key.
  4. Select the tab for your operating system.
  5. Copy the enrollment command shown in the App Launcher.
  6. Run the command in a local terminal on the device you use for SSH.
  7. Follow the prompts, then copy the JSON output.
  8. Return to the App Launcher and paste the JSON into the enrollment field.
  9. Complete the enrollment.

Configure your SSH client for a FIDO2 key

The command creates the identity at ~/.ssh/id_ed25519_sk_cf.

Add the following configuration to your ~/.ssh/config file:

Host *
  IdentityFile ~/.ssh/id_ed25519_sk_cf

Alternatively, supply the identity when you connect:

ssh -i ~/.ssh/id_ed25519_sk_cf <username>@<target IP>

For more information on how OpenSSH uses FIDO2 hardware keys, refer to Yubico's Securing SSH with FIDO2.

Enroll a PIV key for infrastructure apps

PIV key enrollment is separate from the general authenticator enrollment above and requires additional client-side setup.

Before enrolling, you must have a YubiKey with firmware 4.3 or later and a key generated in PIV slot 9a. If you have not generated a PIV key yet, refer to Generate a PIV key.

Generate a PIV key

If you do not already have a PIV key on your YubiKey, generate one in slot 9a:

ykman piv keys generate \
  --algorithm ECCP256 \
  --pin-policy once \
  --touch-policy always \
  9a pubkey.pem

Touch your YubiKey when it blinks to confirm key generation. Then create a self-signed certificate to make the key visible to SSH agents:

ykman piv certificates generate --subject "CN=SSH-Identity" 9a pubkey.pem

After generating the key, generate attestation certificates and continue with enrollment.

Generate attestation certificates

Attestation certificates prove that the key was generated on genuine hardware. Run the following commands to export them from your YubiKey:

ykman piv keys attest 9a leaf.pem
ykman piv certificates export f9 intermediate.pem
  • leaf.pem contains the public key and metadata for the key in slot 9a.
  • intermediate.pem is the YubiKey attestation CA certificate.

Upload certificates to Cloudflare

  1. Go to your organization's App Launcher at <your-team-name>.cloudflareaccess.com.
  2. Log in with an identity provider (IdP), a one-time pin, or with Cloudflare as your IdP.
  3. Go to Account > MFA devices > Add an MFA device.
  4. Select PIV key.
  5. Paste the contents of leaf.pem into the Leaf certificate field.
  6. Paste the contents of intermediate.pem into the Intermediate certificate field.
  7. Select Enroll.

Access extracts and stores the SSH public key from your certificate for future authentication to infrastructure apps. You can enroll multiple PIV keys for backup purposes.

Configure your SSH client

After enrollment, configure your SSH client to use the PIV key. The following example uses yubikey-agent on macOS. For Linux, refer to the yubikey-agent documentation.

  1. Install and start yubikey-agent:

    brew install yubikey-agent
    brew services start yubikey-agent
  2. Extract the SSH public key from your leaf certificate:

    openssl x509 -in leaf.pem -pubkey -noout | ssh-keygen -i -m PKCS8 -f /dev/stdin > ~/.ssh/id_yubikey.pub
  3. Add the following to your ~/.ssh/config:

    Host *
      IdentityAgent /opt/homebrew/var/run/yubikey-agent.sock
      IdentitiesOnly yes
      AddKeysToAgent yes
      IdentityFile ~/.ssh/id_yubikey.pub
  4. Verify that the key is loaded:

    ssh-add -L

    The output should show an ecdsa-sha2-nistp256 key.

Delete an authenticator

Users can delete their own authenticators from the App Launcher. If the user has at least one authenticator enrolled, Access requires them to verify with an existing MFA method before they can remove a device.

  1. Go to your organization's App Launcher at <your-team-name>.cloudflareaccess.com.
  2. Go to Account > MFA devices.
  3. Select the 3-dot menu next to the MFA device, then select Remove MFA device.
  4. If you have other MFA devices enrolled, complete the MFA verification prompt.

Administrators can also delete authenticators on behalf of users.

MFA verification for authenticator changes

When a user has at least one authenticator enrolled, Access requires MFA verification before the user can add or remove an authenticator from the App Launcher. This verification step is separate from the IdP login and uses the user's existing independent MFA device.

After the user completes MFA verification, they have 10 minutes to add or remove authenticators without additional prompts. This window is tied to the current device. After 10 minutes, or if the user switches to a different device, Access requires MFA verification again.

This prevents an attacker with compromised IdP credentials from modifying a user's enrolled authenticators. Even if an attacker gains access to the user's IdP session, they cannot bypass the independent MFA verification step without also possessing the user's enrolled authenticator. If a user loses their only authenticator and cannot verify, an administrator can delete it to allow re-enrollment. Refer to Manage user authenticators.

Manage user authenticators

Administrators can view and delete authenticators enrolled by users. This is useful for resolving lockouts or responding to security events.

View user authenticators

To view a user's enrolled authenticators:

  1. In the Cloudflare dashboard, go to Zero Trust > Team & Resources > Users.
  2. Select a user.
  3. Go to MFA devices. Each entry shows the authenticator's ID, its user-configured name, and the MFA method.

Delete a user authenticator

If a user is locked out or you need to revoke an authenticator for security reasons, you can delete it from the dashboard or API.

  1. In the Cloudflare dashboard, go to Zero Trust > Team & Resources > Users.
  2. Select the user whose authenticator you want to delete.
  3. Under MFA devices, find the authenticator and select Delete.

The user will need to enroll a new authenticator the next time they access an application that requires MFA.

Send a DELETE request to remove a specific authenticator:

Delete a user's MFA devicebash
curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/users/$USER_ID/mfa_authenticators/$AUTHENTICATOR_ID" \
	--request DELETE \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

Parameters:

  • user_id — The UUID of the user. You can find this in the user details under Team & Resources > Users.
  • authenticator_id — The unique identifier for the authenticator.

Lockout recovery

If a user loses access to all of their enrolled authenticators:

  1. Delete the user's authenticators.
  2. The user can then access a protected application and will be provided a link to enroll a new authenticator.
  3. Alternatively, share the direct enrollment link with the user: <your-team-name>.cloudflareaccess.com/AddMfaDevice.

Was this helpful?