Managed OAuth
When you protect an application with Cloudflare Access, by default non-browser clients — such as CLIs, AI agents, SDKs, and scripts — cannot complete the browser-based login redirect. They receive a 302 redirect with no usable token or authorization endpoint.
Managed OAuth solves this by turning Access into a standard OAuth 2.0 authorization server for your application. Access enforces the same policies as a browser login, and your origin sees no difference.
- A self-hosted Access application or an MCP server portal
- An OAuth client that supports RFC 8707 ↗
- In the Cloudflare dashboard ↗, go to Zero Trust > Access controls > Applications.
- Find the application you want to configure, then select the three dots on the right > Edit.
- Go to the Advanced settings tab and turn on Managed OAuth.
- (Optional) Configure Managed OAuth settings.
- Select Save application.
-
Get your existing Access application configuration:
At least one of the following token permissions is required:Required API token permissions
Access: Apps and Policies WriteAccess: Apps and Policies Read
Get an Access application curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID" \--request GET \--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -
Make a
PUTrequest and setoauth_configuration.enabledtotrue. To avoid overwriting your existing configuration, the request body should contain all fields returned by the previousGETrequest.
At least one of the following token permissions is required:Required API token permissions
Access: Apps and Policies Write
Update an Access application curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID" \--request PUT \--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \--json '{"oauth_configuration": {"enabled": true}}'
To test, open an RFC 8707-compliant OAuth client and make a request to your application. The client should open a browser window prompting you to log in to Access. Refer to the Authorization flow section for more details.
Managed OAuth is available on MCP server portals and is the mechanism that allows MCP clients to authenticate users through the portal without a browser cookie flow.
- In the Cloudflare dashboard ↗, go to Zero Trust > Access controls > AI controls.
- Find the portal you want to configure, then select the three dots on the right > Edit.
- Go to the Advanced settings tab, turn on Managed OAuth.
- (Optional) Configure Managed OAuth settings.
- Select Save application.
-
Get your existing configuration for the portal's underlying Access application:
At least one of the following token permissions is required:Required API token permissions
Access: Apps and Policies WriteAccess: Apps and Policies Read
Get an Access application curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID" \--request GET \--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -
Make a
PUTrequest and setoauth_configuration.enabledtotrue. To avoid overwriting your existing configuration, the request body should contain all fields returned by the previousGETrequest.
At least one of the following token permissions is required:Required API token permissions
Access: Apps and Policies Write
Update an Access application curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID" \--request PUT \--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \--json '{"oauth_configuration": {"enabled": true}}'
To test, open an MCP client and connect to the MCP portal. The client should open a browser window prompting you to log in to Access. Refer to the Authorization flow section for more details.
Configure these settings in the Advanced settings tab of your self-hosted app or MCP server portal.
- Allow localhost clients: Allow any client with redirect URIs on
localhost. - Allow loopback clients: Allow any client with redirect URIs on
127.0.0.1. - Allowed redirect URIs: Redirect URIs allowed for dynamically registered clients (for example,
https://playground.ai.cloudflare.com/*). The URL must usehttps. Paths may end in/*to match all sub-paths. - Grant session duration: How long the OAuth refresh token remains valid.
- Access token lifetime: How long an OIDC Access token can be used to authenticate with your application. Cloudflare recommends configuring a short Access token lifetime (default 15 minutes) in conjunction with a longer Grant session duration. When the access token expires, Cloudflare uses the refresh token to issue a new one after re-evaluating the user against your Access policies. When the refresh token expires, the user must re-authenticate with the identity provider.
Configure these settings via the oauth_configuration object on the Access applications endpoint.
| Dashboard setting | API field |
|---|---|
| Allow localhost clients | dynamic_client_registration.allow_any_on_localhost |
| Allow loopback clients | dynamic_client_registration.allow_any_on_loopback |
| Allowed redirect URIs | dynamic_client_registration.allowed_uris |
| Grant session duration | grant.session_duration |
| Access token lifetime | grant.access_token_lifetime |
-
Get your existing Access application configuration:
At least one of the following token permissions is required:Required API token permissions
Access: Apps and Policies WriteAccess: Apps and Policies Read
Get an Access application curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID" \--request GET \--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -
Make a
PUTrequest with your Managed OAUth settings. To avoid overwriting your existing configuration, the request body should contain all fields returned by the previousGETrequest.
At least one of the following token permissions is required:Required API token permissions
Access: Apps and Policies Write
Update an Access application curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps/$APP_ID" \--request PUT \--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \--json '{"oauth_configuration": {"enabled": true,"dynamic_client_registration": {"enabled": true,"allow_any_on_localhost": true,"allow_any_on_loopback": true,"allowed_uris": ["https://playground.ai.cloudflare.com/*"]},"grant": {"access_token_lifetime": "5m","session_duration": "24h"}}}'
When managed OAuth is enabled, Access returns a 401 response instead of a 302 redirect to non-browser clients. The 401 includes a WWW-Authenticate header that points the client to Access's OAuth discovery metadata.
The authorization flow proceeds as follows:
-
The client fetches the OAuth authorization server metadata from the
/.well-known/endpoint:https://<your-app-domain>/.well-known/oauth-authorization-serverThis endpoint conforms to RFC 8414 ↗ and RFC 9728 ↗ and returns the authorization and token endpoint URLs for the application.
-
The client initiates an authorization code flow. It opens the user's browser to the Access authorization endpoint, where the user logs in to their IdP as usual.
-
Access issues an OAuth access token to the client. The client uses this token in subsequent requests to the protected application.
Both managed OAuth and service tokens allow non-browser clients to authenticate with Access-protected applications, but they serve different use cases:
| Managed OAuth | Service tokens | |
|---|---|---|
| Authentication model | User-based — the end user logs in through their identity provider | Machine-based — a shared secret authenticates the service itself |
| Best for | Interactive CLI tools, AI agents, SDKs where a human initiates the request | Fully automated systems, cron jobs, CI/CD pipelines, server-to-server communication |
| User identity | Access knows which user made the request | No user identity — requests are attributed to the service token |
| Policy enforcement | Can use identity-based policies (for example, require specific groups or emails) | Requires a Service Auth policy action |
| Credential management | No shared secrets to distribute — users authenticate with their own credentials | Requires distributing and rotating Client ID and Client Secret |
Use managed OAuth when you want non-browser clients to authenticate users the same way a browser would — the user logs in once, and the client receives an OAuth token to make requests on their behalf.
Use service tokens when no human is involved and you need a machine identity to access your application programmatically.