Wiring GitHub, Entra ID or Okta as a Cloudflare Access login method
This page covers the Cloudflare Access path, where Access sits in front of the console and the engine trusts a signed assertion from it. It is not the native single sign-on path. If you want the engine to talk to your provider directly, read connect OIDC or OAuth2 instead.
Access is optional. Whether you set up Access never gates a backup, a recovery or any data-plane operation in the engine. What it buys is attributability: on the shared admin token alone, the engine knows a call was authorised, but not by whom. The engine’s own passkey sign-in and its native OIDC and SAML connections also identify each person without Access. Identity and access makes that case and sets the engine variables.
What it costs, and the zero-licence path
Pricing changes, so verify each vendor’s current terms before you commit to one.
Cloudflare Zero Trust has a free tier for up to 50 users, and paid plans are per seat beyond that. Check the current limit at cloudflare.com/plans/zero-trust.
GitHub as a login method is free, and Cloudflare Access authenticates through GitHub OAuth at no extra cost from either side. GitHub team membership can drive group-based roles, using the account data you already have. GitHub plus the Zero Trust free tier, under the seat limit, is therefore the zero-licence attributable path: per-person sign-in and team-based roles at no licence cost.
Okta and Entra ID are paid products. Pick one of those when your organisation already pays for it, not to get Access working.
The shape is the same for every provider
Three steps, whichever provider you pick:
- Create a login method in Cloudflare Zero Trust.
- Create an Access application over the engine and console custom domains.
- Set
CF_ACCESS_TEAM_DOMAINandCF_ACCESS_AUDin the engine’swrangler.toml.
You run every one of these in the Cloudflare dashboard and at your provider. The console links out and never captures a client secret.
The engine verifies the RS256-signed JWT that Access injects on each request, in the
cf-access-jwt-assertion header. It fetches Cloudflare’s public keys, then checks the signature,
the issuer, the audience, the expiry and the not-before. Only then does it trust the email and the
groups inside. Trusting that header without verifying it would be an authentication bypass, so the
engine does not.
GitHub
On GitHub. Go to Settings, then Developer settings, then OAuth Apps, then New OAuth App. Set the
authorisation callback URL to https://<your-team>.cloudflareaccess.com/cdn-cgi/access/callback.
Note the Client ID and generate a Client Secret.
In Cloudflare Zero Trust. Go to Settings, then Authentication, then Login methods, then Add new, then GitHub. Enter the Client ID and the Client Secret, and save.
For group-based roles. Access can request the read:org scope, which lets it read the caller’s
team memberships and put them in the groups claim. Turn that on in the login-method settings. The
engine then receives groups as <org>/<team-slug>, for example myorg/ops. Use that exact form in
a group-to-role mapping.
Microsoft Entra ID
On Entra ID. In the Azure portal, go to Microsoft Entra ID, then App registrations, then New
registration. Set the redirect URI type to Web, and the URI to the same
cloudflareaccess.com/cdn-cgi/access/callback address. Note the Application (client) ID, then
create a client secret under Certificates and secrets.
Under API permissions, add User.Read: Cloudflare Access needs it for the email claim. For group
claims, add GroupMember.Read.All as well and grant admin consent. Then, under Token configuration,
add a groups claim.
Check your plan before you rely on groups. Emitting group claims to an external relying party can require an Entra ID P1 or P2 plan. Verify that with Microsoft rather than discovering it during a sign-in.
In Cloudflare Zero Trust. Go to Login methods, then Add new, then Azure AD. Enter your tenant ID, the Application (client) ID and the client secret. Turn on Support groups.
What the engine receives. Entra sends group object IDs, which are GUIDs rather than display
names, unless you configure optional claims to emit group_names. Map on the exact string the
engine receives, which GET /admin/whoami shows you after you sign in.
Okta
On Okta. In the Admin Console, go to Applications, then Applications, then Create App Integration. Choose OIDC as the sign-in method and Web Application as the application type. Set the redirect URI to the same callback address, then note the Client ID and generate a Client Secret.
For group-based roles. Open the application’s Sign On tab, then Edit, then OpenID Connect ID
Token. Add a groups claim with a filter for the groups you want forwarded, such as a regex .* for all. The claim name must be groups.
In Cloudflare Zero Trust. Go to Login methods, then Add new, then Okta. Enter your Okta domain, the Client ID and the Client Secret. Turn on Support groups, and save.
What the engine receives. Okta sends group display names, not IDs, so map on the display name. This is the opposite of Entra, and it is the one detail that catches people running both.
The Access application, and the AUD tag
Do this once, whichever provider you chose. In Cloudflare Zero Trust, go to Access, then Applications, then Add an application, then Self-hosted. Add both the engine custom domain and the console custom domain as application domains. Configure the policy to allow the login method you just created.
After you save, Cloudflare generates an AUD tag for the application. Copy it, along with your
Zero Trust team name, into the engine’s variables. These two are identifiers rather than secrets, so
they belong in wrangler.toml vars. Identity and
access covers that
step and the deploy that follows.
Good to know
- In the default topology the engine has no public hostname, so the Access application covers the console’s domain only. In the split topology the engine has its own custom domain. Put both domains on one application there, because a policy over the console alone leaves the engine reachable without Access.
- The group string is provider-specific, so a mapping that works on Okta will not match on Entra.
GET /admin/whoamiis the fastest way to see what the engine actually received, and it settles a group mapping that is not matching faster than reading the provider’s configuration again.
Last updated .