> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-docs-5625.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Learn how to set up Cloudflare for use as the custom domain proxy for Auth0.

# Configure Cloudflare as Reverse Proxy

<Card title="Availability varies by Auth0 plan">
  Your Auth0 plan or custom agreement affects the availability of this feature. To learn more, read [Auth0's Pricing Page](https://auth0.com/pricing).
</Card>

To set up Cloudflare as a reverse proxy using the recommended approach, a Cloudflare Enterprise Plan with the following features is required:

| Feature | Description |
| - | - |
| Host Header Override | Rewrite Host headers using different Cloudflare rules. To learn more, read [Rewrite Host headers on Cloudflare Docs](https://developers.cloudflare.com/rules/origin-rules/tutorials/change-uri-path-and-host-header/). |
| True-Client-IP Header | Enabling the True-Client-IP Header adds the True-Client-IP header to all requests to your origin server, which includes the end user’s IP address. To learn more, read [Understanding the True-Client-IP Header on Cloudflare](https://developers.cloudflare.com/network/true-client-ip-header/). |

## Configure Cloudflare

<Warning>
  As a prerequisite, the parent domain for your chosen custom domain must be [added and activated within the Cloudflare dashboard](https://developers.cloudflare.com/learning-paths/get-started/add-domain-to-cf/minimize-downtime/#activate-your-domain). Also, confirm that your desired custom domain does not already exist within your Cloudflare zone. If it already exists, Cloudflare verification will fail.
</Warning>

To configure Cloudflare as a reverse proxy, you’ll need to create a CNAME record, a Page Rule, and a Transform Rule in Cloudflare.

1. [Configure and verify a Custom Domain with Self-Managed Certificates](/docs/customize/custom-domains/self-managed-certificates) if you haven't already. Make note of the **Origin Domain Name** and **cname-api-key** values since you'll need these later.
2. In the Cloudflare dashboard for the target zone, [create a CNAME record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) with the following settings:

   | Setting | Value |
   | - | - |
   | Name | The custom domain name. |
   | Target | The **Origin Domain Name** value recorded earlier. |
   | Proxy Status | `Proxied` |
3. [Create a Page Rule](https://developers.cloudflare.com/rules/page-rules/) scoped to all URLs under the chosen custom domain and with the following settings:

   | Setting | Value |
   | - | - |
   | Host Header Override | The **Origin Domain Name** value recorded earlier. |
   | True-Client-IP | `Enable` |
4. [Create a Transform Rule](https://developers.cloudflare.com/rules/transform/request-header-modification/create-dashboard/):

   <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
     While it is possible to use Cloudflare Workers instead of Page and Transform rules to set up a reverse proxy that meets the requirements for a self-managed certificate custom domain, we recommend using the rules-based approach because it eliminates the need for custom code.
   </Callout>

   1. Switch to the **Modify Request Header** view.
   2. Select **Create Rule** and provide a name of your choice.
   3. Under **When incoming requests match**, select **Custom filter expression** and set an expression that scopes the Rule to requests associated with the chosen custom domain. For example, use an exact match on the **Hostname** field.
   4. Under Modify request header, select **Set static**, and then set the following fields:

      | Field | Value |
      | - | - |
      | Header name | `cname-api-key` |
      | Value | The **cname-api-key** value recorded earlier. |
5. Ensure that [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) is enabled and [encryption mode](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/) is set, at least, to **Full** for your chosen custom domain.

## Use Managed Challenges

Cloudflare's [Managed Challenges](https://developers.cloudflare.com/cloudflare-challenges/challenge-types/challenge-pages/#managed-challenges) let you filter bot traffic before requests reach Auth0 Universal Login. When a request matches your rule, Cloudflare intercepts it and presents a verification challenge. Because challenge pages return HTML, Managed Challenges are only compatible with browser-based flows — applying them to API endpoints or headless flows will break those flows because the client receives an HTML challenge page instead of the expected response.

### Universal Login browser-based endpoints

The following endpoints serve HTML pages to a browser and are compatible with Managed Challenges:

| Endpoint | Description |
| - | - |
| `/u/email-verification` | Email verification |
| `/u/login` | Identifier and identifier-first prompts |
| Organization endpoints: <br /><ul><li>`u/organization`</li><li>`/u/organization-picker`</li><li>`/u/pre-organization-picker`</li></ul> | Organization selection prompts |
| `/u/login/password` | Password prompt |
| `/u/login-email-verification` | Email verification prompt |
| `/u/signup` | Identifier prompts |
| `/u/signup/password` | Password prompt |
| `/u/consent` | Consent prompt |
| `/u/customized-consent` | Customized consent prompt |
| `/u/reset-password` | Password reset prompts |
| `/u/reset-password/request` | Email/username prompt for password reset |
| `/u/reset-password/change` | New password prompt |
| `/u/reset-verify` | Password reset verification |
| `/u/mfa-begin-enroll-options` | MFA enrollment factor selection |
| `/u/mfa-enroll-options` | MFA enrollment options |
| `/u/mfa-otp` | One-time password prompts |
| `/u/mfa-push` | Push notification prompts |
| `/u/mfa-webauthn` | WebAuthn and passkey prompts |
| `/u/mfa-recovery-code` | Recovery code prompts |
| `/u/mfa-sms` | SMS prompts |
| `/u/mfa-email` | MFA email prompts |
| `/u/mfa-voice` | MFA voice prompts |
| `/u/passkey-enrollment` | Passkey enrollment |

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  If you use Classic Universal Login, also include `/login` in your Managed Challenge rule.
</Callout>

### Endpoints to exclude

Do not apply a Managed Challenge to the following endpoints. These are called by servers, SDKs, or resource servers and cannot solve an interactive challenge:

| Endpoint | Description |
| - | - |
| `/oauth/token` | Token endpoint |
| `/oauth/revoke` | Token revocation endpoint |
| `/userinfo` | UserInfo endpoint |
| `/.well-known/openid-configuration` | OIDC discovery document |
| `/.well-known/jwks.json` | JSON Web Key Set; fetched by resource servers for token validation |
| `/api/v2/*` | Management API |
| `/co/authenticate` | Cross-origin authentication |
| `/dbconnections/signup` | Database connections: signup |
| `/dbconnections/change_password` | Database connections: change password |
| `/usernamepassword/login` | Classic Universal Login form submission |
| `/mfa/challenge` | Challenge request |
| `/mfa/associate` | Authenticator association |
| `/passwordless/start` | Passwordless: initiation request |
| `/samlp/*` | SAML protocol endpoints |
| `/wsfed/*` | WS-Federation endpoints |
| `/v2/logout` | May be called server-side in back-channel logout flows |

### Example rule

To apply Managed Challenges only to browser-based Universal Login flows, create a [WAF Custom Rule](https://developers.cloudflare.com/waf/custom-rules/) in Cloudflare. Set the rule action to **Managed Challenge** and use the following expression, replacing `YOUR_CUSTOM_DOMAIN` with your custom domain (for example, `login.example.com`):

```text theme={null}
(http.host eq "YOUR_CUSTOM_DOMAIN" and (
  http.request.uri.path eq "/authorize" or
  starts_with(http.request.uri.path, "/u/") or
  http.request.uri.path eq "/login"
))
```

This scopes the challenge to headed Universal Login endpoints only and prevents disruption to API and machine-to-machine traffic.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  A few use cases may behave differently:

  * **Clearance cookie persistence**: Once a browser solves a Managed Challenge, Cloudflare issues a clearance cookie that typically persists for the session. Depending on your configuration, scoping the rule to `/authorize` alone may be sufficient to cover the full Universal Login flow without applying it to every `/u/*` path.
  * **Non-OAuth entry points**: Flows that start from SAML SP-initiated or WS-Federation entry points use `/samlp/*` or `/wsfed/*` instead of `/authorize`. These paths are in the exclusion list and should not have a Managed Challenge applied to them.
</Callout>

## Configure Auth0

Call the Auth0 <Tooltip tip="Management API: A product to allow customers to perform administrative tasks." cta="View Glossary" href="/docs/glossary?term=Management+API">Management API</Tooltip> [Update custom domain configuration](https://auth0.com/docs/api/management/v2#!/Custom_Domains/patch_custom_domains_by_id) endpoint with the following payload in the body:

```json lines theme={null}
{
  "custom_client_ip_header": "true-client-ip"
}
```

This will configure Auth0 to take the end user's IP address from HTTP header `true-client-ip`.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Always aim to use `true-client-ip`. Using HTTP header `cf-connecting-ip` for this purpose is unsupported by Cloudflare.
</Callout>

## Learn more

* [Configure Features to Use Custom Domains](/docs/customize/custom-domains/configure-features-to-use-custom-domains)
* [TLS (SSL) Versions and Ciphers](/docs/customize/custom-domains/self-managed-certificates/tls-ssl)
