Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/content/changelog/access/2026-03-06-independent-mfa.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: Independent MFA for Access applications
description: Enforce multi-factor authentication for Access applications without relying on your identity provider.
date: 2026-03-06
products:
- access
---

Cloudflare Access now supports independent multi-factor authentication (MFA), allowing you to enforce MFA requirements without relying on your identity provider (IdP). This feature addresses common gaps in IdP-based MFA, such as inconsistent MFA policies across different identity providers or the need for additional security layers beyond what the IdP provides.

Independent MFA supports the following authenticator types:

- **Authenticator application** — Time-based one-time passwords using apps like Google Authenticator, Microsoft Authenticator, or Authy.
- **Security key** — Hardware security keys such as YubiKeys.
- **Biometrics** — Built-in device authenticators including macOS Touch ID, Face ID, and Windows Hello.

## Configuration levels

You can configure MFA requirements at three levels:

| Level | Description |
| ---------------- | -------------------------------------------------------------- |
| **Organization** | Enforce MFA by default for all applications in your account. |
| **Application** | Require or turn off MFA for a specific application. |
| **Policy** | Require or turn off MFA for users who match a specific policy. |

Settings at lower levels (policy) override settings at higher levels (organization), giving you granular control over MFA enforcement.

## User enrollment

Users enroll their authenticators through the [App Launcher](/cloudflare-one/access-controls/access-settings/app-launcher/). To help with onboarding, administrators can share a direct enrollment link: `<your-team-name>.cloudflareaccess.com/#/AddMfaDevice`.
Comment thread
ranbel marked this conversation as resolved.

For more information, refer to [Enforce MFA](/cloudflare-one/access-controls/policies/mfa-requirements/#enforce-independent-mfa).
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
pcx_content_type: how-to
title: Independent MFA
sidebar:
order: 4
tags:
- Authentication
---

import { Tabs, TabItem, APIRequest } from "~/components";

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 factor before granting access to the application.

Before you can [enforce independent MFA on applications and policies](/cloudflare-one/access-controls/policies/mfa-requirements/#enforce-independent-mfa), you must turn on independent MFA at the organization level.

## Prerequisites

- An [authentication domain](/cloudflare-one/setup/) set for your organization.

## Turn on independent MFA

<Tabs syncKey="dashPlusAPI"> <TabItem label="Dashboard">

1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Access controls** > **Access settings**.
2. In the **Allow multi-factor authentication (MFA)** section, select the authenticator types you want to allow in your organization:
- **Authenticator application** — Time-based one-time passwords from authenticator apps.
- **Security key** — Hardware security keys such as YubiKeys.
- **Biometrics** — Device-bound authenticators such as macOS Touch ID, Face ID, and Windows Hello.
3. Set a **Global MFA session duration**. This determines how long a successful MFA authentication remains valid before the user must authenticate again. The default is 24 hours.
4. Select **Save**.

</TabItem> <TabItem label="API">

Send a `PUT` request to update your Access organization settings with MFA configuration:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be PATCH? We support PUT but that means sending all existing values too

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a PATCH option in the API docs, only PUT: https://developers.cloudflare.com/api/resources/zero_trust/subresources/organizations/methods/update

Do we support PATCH?


<APIRequest
path="/accounts/{account_id}/access/organizations"
method="PUT"
json={{
mfa_config: {
allowed_authenticators: ["totp", "biometrics", "security_key"],
session_duration: "24h",
},
}}
/>

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 (YubiKeys).

Set `session_duration` to a duration string (for example, `30m`, `1h`, `24h`).
Comment thread
ranbel marked this conversation as resolved.

</TabItem> </Tabs>

After you turn on independent MFA, users can [enroll authenticators](/cloudflare-one/access-controls/policies/mfa-requirements/#enroll-authenticators) through the [App Launcher](/cloudflare-one/access-controls/access-settings/app-launcher/).

## Enforce MFA for all applications

<Tabs syncKey="dashPlusAPI"> <TabItem label="Dashboard">

1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Access controls** > **Access settings**.
2. In the **Allow multi-factor authentication (MFA)** section, select **Apply global MFA settings by default**.

</TabItem> <TabItem label="API">

Send a `PUT` request with `mfa_required_for_all_apps` set to `true`:

<APIRequest
path="/accounts/{account_id}/access/organizations"
method="PUT"
json={{
mfa_required_for_all_apps: true,
}}
/>

</TabItem> </Tabs>

All Access applications will require MFA using the organization-level settings (allowed authenticators and session duration). Individual applications and policies can override this setting by selecting **Custom MFA settings** or **Disable MFA**. For more information, refer to [Configure independent MFA for an application](/cloudflare-one/access-controls/policies/mfa-requirements/#configure-independent-mfa-for-an-application).

:::note
The [App Launcher](/cloudflare-one/access-controls/access-settings/app-launcher/) is exempt from the global MFA requirement. Users must be able to access the App Launcher without MFA to enroll their authenticators.
:::

## Turn off independent MFA

<Tabs syncKey="dashPlusAPI"> <TabItem label="Dashboard">

1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Access controls** > **Access settings**.
2. In the **Allow multi-factor authentication (MFA)** section, toggle off all authenticator types. If any applications or policies use custom MFA settings, you must remove those custom settings first.

</TabItem> <TabItem label="API">

Send a `PUT` request with an empty `allowed_authenticators` array:

<APIRequest
path="/accounts/{account_id}/access/organizations"
method="PUT"
json={{
mfa_config: {
allowed_authenticators: [],
},
}}
/>

</TabItem> </Tabs>

:::caution
Turning off independent MFA removes MFA enforcement from all applications. Verify that your identity provider MFA policies provide adequate coverage before you turn off this feature.
:::

## 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

<Tabs syncKey="dashPlusAPI"> <TabItem label="Dashboard">

1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Team & Resources** > **Users**.
2. Select a user.
3. In the **MFA devices** section, view the user's enrolled authenticators. Each entry shows the MFA ID, device name, and the MFA method.

</TabItem> <TabItem label="API">

Send a `GET` request to list all authenticators for a user:

<APIRequest
path="/accounts/{account_id}/access/users/{user_id}/mfa_authenticators"
method="GET"
/>

</TabItem> </Tabs>

### 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.

<Tabs syncKey="dashPlusAPI"> <TabItem label="Dashboard">

1. In the [Cloudflare dashboard](https://dash.cloudflare.com/), go to **Zero Trust** > **Team & Resources** > **Users**.
2. Select the user whose authenticator you want to delete.
3. In the **MFA devices** section, 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.

</TabItem> <TabItem label="API">

Send a `DELETE` request to remove a specific authenticator:

<APIRequest
path="/accounts/{account_id}/access/users/{user_id}/mfa_authenticators/{authenticator_id}"
method="DELETE"
/>

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.

</TabItem> </Tabs>

### Lockout recovery

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

1. Delete the user's authenticators using the steps above.
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`.

:::note
To prevent lockouts, recommend that users enroll multiple authenticators (for example, a security key and an authenticator application) when available.
Comment thread
ranbel marked this conversation as resolved.
:::
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ title: Session management
sidebar:
order: 2
tags:
- JSON web token (JWT)
- Authentication
- JSON web token (JWT)
- Authentication
---

import { GlossaryTooltip, Render } from "~/components";
Expand All @@ -16,9 +16,9 @@ A user session determines how long a user can access an Access application witho

When a user logs in to an application protected by Access, Access validates their identity against your Access policies and generates two signed JSON Web Tokens (JWTs):

| Token | Description | Expiration | Storage |
| ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
| Global session token | Stores the user's identity from the IdP and provides single sign-on (SSO) functionality for all Access applications. | [Global session duration](#global-session-duration) | Your Cloudflare <GlossaryTooltip term="team domain">team domain</GlossaryTooltip> |
| Token | Description | Expiration | Storage |
| ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| Global session token | Stores the user's identity from the IdP and provides single sign-on (SSO) functionality for all Access applications. | [Global session duration](#global-session-duration) | Your Cloudflare <GlossaryTooltip term="team domain">team domain</GlossaryTooltip> |
| [Application token](/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/application-token/) | Allows the user to access a specific Access application. | [Policy session duration](#policy-session-duration), which defaults to the [application session duration](#application-session-duration) | The hostname protected by the Access application |

The user can access the application for the entire duration of the application token's lifecycle. When the application token expires, Cloudflare will automatically issue a new application token if the global token is still valid (and the user's identity still passes your Access policies). If the global token has also expired, the user will be prompted to re-authenticate with the IdP.
Expand All @@ -32,6 +32,10 @@ In summary, Access checks sessions from most specific to least specific:
3. **[Application session](#application-session-duration)** — The default policy session duration for all policies in the application.
4. **[Global session](#global-session-duration)** — Controls how often the user must log in to the IdP across all applications.

:::note
If you use [independent MFA](/cloudflare-one/access-controls/access-settings/independent-mfa/), the MFA session duration is managed separately from the sessions listed above. A user can have a valid application session but still be prompted for MFA if their MFA session has expired. For more information, refer to [MFA session duration](/cloudflare-one/access-controls/policies/mfa-requirements/#mfa-session-duration).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is accurate

Application session (or policy session duration) always last however long they're defined - if MFA expires while an app session is active, the user can still access the app. They're not prompted for MFA until they go to a different app

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it applies mid session, but if you try to access the application again from another tab, wouldn't MFA fire?

:::

Refer to the [Order of enforcement](#order-of-enforcement) flowchart for a visual representation.

<Render file="access/one-time-pin-warning" product="cloudflare-one" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,11 @@ Some SaaS applications provide the Redirect URL after you [configure the SSO pro

14. Configure [App Launcher settings](/cloudflare-one/access-controls/access-settings/app-launcher/) for the application. If **Show application in App Launcher** is enabled, then you must enter an **App Launcher URL**. The App Launcher URL is provided by the SaaS application. It may match the base URL portion of **Redirect URL** (`https://<INSTANCE-NAME>.example-app.com`) but could be a different value.

15. <Render file="access/access-block-page" product="cloudflare-one" />
15. <Render file="access/configure-independent-mfa" product="cloudflare-one" />

16. Select **Save application**.
16. <Render file="access/access-block-page" product="cloudflare-one" />

17. Select **Save application**.

## 3. Configure SSO in your SaaS application

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ If you are using Okta, Microsoft Entra ID (formerly Azure AD), Google Workspace,

14. (Optional) Configure [App Launcher settings](/cloudflare-one/access-controls/access-settings/app-launcher/) for the application.

15. <Render file="access/access-block-page" product="cloudflare-one" />
15. <Render file="access/configure-independent-mfa" product="cloudflare-one" />

16. Select **Save application**.
16. <Render file="access/access-block-page" product="cloudflare-one" />

17. Select **Save application**.

## 3. Configure SSO in your SaaS application

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,26 @@ This feature replaces the legacy [private network app type](/cloudflare-one/acce

11. (Optional) Configure [App Launcher settings](/cloudflare-one/access-controls/access-settings/app-launcher/) for the application.

12. (Optional) Turn on **Allow clientless access** to allow users to access this private hostname or IP without the Cloudflare One Client. Users who pass your Access policies will see a tile in their App Launcher which points to a prefixed URL such as `https://<your-teamname>.cloudflareaccess.com/browser/https://wiki.internal.local/`. The link will route traffic to the application through [Clientless Web Isolation](/cloudflare-one/remote-browser-isolation/setup/clientless-browser-isolation/). This setting is useful for users on unmanaged devices or contractors who cannot install a device client.
12. <Render file="access/configure-independent-mfa" product="cloudflare-one" />

13. (Optional) Turn on **Allow clientless access** to allow users to access this private hostname or IP without the Cloudflare One Client. Users who pass your Access policies will see a tile in their App Launcher which points to a prefixed URL such as `https://<your-teamname>.cloudflareaccess.com/browser/https://wiki.internal.local/`. The link will route traffic to the application through [Clientless Web Isolation](/cloudflare-one/remote-browser-isolation/setup/clientless-browser-isolation/). This setting is useful for users on unmanaged devices or contractors who cannot install a device client.

:::note
Ensure your [remote browser permissions](/cloudflare-one/remote-browser-isolation/setup/clientless-browser-isolation/) allow users of this application to open Clientless Web Isolation links.
:::

13. <Render file="access/access-block-page" product="cloudflare-one" />
14. <Render file="access/access-block-page" product="cloudflare-one" />

14. Select **Next**.
15. Select **Next**.

15. <Render
16. <Render
file="access/self-hosted-app/advanced-settings"
product="cloudflare-one"
/>

These settings only apply to private hostnames and require [Gateway TLS decryption](/cloudflare-one/traffic-policies/http-policies/tls-decryption/).

16. Select **Save**.
17. Select **Save**.

Users can now connect to your private application after authenticating with Cloudflare Access.

Expand Down
Loading