Microsoft Entra
Wiring Microsoft Entra (formerly Azure AD) as Flux's OIDC identity provider — v2 endpoints, token versions, and the minimal Flux config.
Microsoft Entra ID (the new name for Azure Active Directory) exposes two OIDC endpoint versions, and they are not interchangeable. Flux requires the v2.0 endpoints — v1 tokens have a different claim shape and a different issuer URL, and Flux’s strict claim validation will reject them. The abstract Flux contract is in Configuring OIDC; this page is the Entra-specific recipe.
What to register at Entra
Two things, in the Entra portal under “App registrations”:
-
App registration. Create one for Flux (e.g.,
flux-server):- Supported account types: Single tenant for one-org deployments; multi-tenant only if you really mean it (multi-tenant means any Entra org can issue tokens for your app).
- Redirect URI: required only if a browser flow is involved. Flux does not host a redirect endpoint, so this is for whatever frontend is acquiring tokens on the user’s behalf.
-
Token version setting. This is the critical Entra-specific step. In the app’s Manifest, set:
"accessTokenAcceptedVersion": 2Without this, Entra issues v1 access tokens with the v1 issuer (
https://sts.windows.net/<tenant>/) and v1 claim shapes (audis often the resource URI rather than the client ID;oidinstead ofsubfor some claim semantics). v1 tokens will not validate against a v2-configured Flux.
The issuer URL is https://login.microsoftonline.com/<tenant-id>/v2.0 (no trailing slash). Replace <tenant-id> with your tenant’s directory ID (a GUID). Discovery is at <issuer>/.well-known/openid-configuration.
The audience is either:
- The Application (client) ID GUID of the app registration, or
- The App ID URI you configured under “Expose an API” (e.g.,
api://flux-server).
Pick one and stick with it. Whichever you choose is what you set in Flux’s audience config.
Signing algorithm is RS256. Entra also rotates keys frequently; Flux’s jwks_cache_ttl (default 3600s) is the window inside which a key rotation propagates without restart.
Vendor-specific gotchas
- v1 vs v2 tokens. Covered above.
accessTokenAcceptedVersion: 2in the manifest is mandatory. Without it, you get v1 tokens regardless of which version endpoint your client calls. - Issuer URL must include
/v2.0. A barehttps://login.microsoftonline.com/<tenant>is the v1 issuer. Flux comparesissstrictly against the configuredissuer; mismatch is a 401. subvsoid. Entra ID tokens include bothsub(subject, pairwise per-app pseudonymous identifier) andoid(object ID, stable per user across all apps in the tenant). Flux’s principal lookup usessub. If you want the same Entra user to appear as the same principal across multiple Flux deployments, you would need to register them per-deployment bysub, or roll a custom claim that exposes a stable identifier.oidis in the token but Flux does not use it for lookup.- Multi-tenant apps. If your app registration is multi-tenant,
issbecomeshttps://login.microsoftonline.com/<actual-tenant-of-the-caller>/v2.0— different for every caller. Flux comparesissexactly, so multi-tenant against a single-tenantissuerconfig fails. For multi-tenant Flux deployments, use the tenant-independentcommonplaceholder issuer (https://login.microsoftonline.com/common/v2.0); be aware that this disables tenant-level access control at the IdP layer and you must enforce it elsewhere (e.g., a Flux-side check on atidclaim via a reverse proxy). - Group claims. Entra can stamp
groups(as object IDs) into tokens via the token configuration. Flux does not read groups —roles_claimis deprecated and roles come from the principals registry. Use Entra groups only as an out-of-band signal. - App roles. Entra has an “App roles” feature that stamps
rolesclaims into tokens. Same story: Flux ignores it. - Tenant ID in the issuer is a GUID, not a domain. Even if your tenant has a friendly domain (
example.onmicrosoft.com), the issuer URL embeds the directory ID GUID. Pull the discovery document to confirm.
The minimal Flux config
[flux.security.auth.oidc]
enabled = true
issuer = "https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/v2.0"
audience = "11111111-1111-1111-1111-111111111111"
default_user_roles = ["viewer"]
Replace the 00000000-… with your tenant ID GUID and 11111111-… with the Application (client) ID GUID (or the App ID URI like api://flux-server). default_user_roles opts into auto-provisioning; omit for manual principal registration.
jwks_cache_ttl = 3600 and clock_skew = 30 are the defaults and are fine for Entra.
Verification
curl -s https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration | jq .
Confirm:
issuerishttps://login.microsoftonline.com/<tenant-id>/v2.0and matches your Flux config exactly.id_token_signing_alg_values_supportedcontainsRS256.jwks_uriis reachable from the Flux host.
Smoke-test a client-credentials access token:
curl -s --request POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data 'grant_type=client_credentials' \
--data 'client_id=<app-client-id>' \
--data 'client_secret=<app-client-secret>' \
--data 'scope=api://flux-server/.default' \
| jq -r .access_token
Decode the payload and verify:
issends in/v2.0(this confirms v2 token).veris"2.0"(also confirms v2 token).audmatches your configured Fluxaudience.sub,expare present.
If iss is https://sts.windows.net/<tenant>/ or ver is "1.0", the manifest still has accessTokenAcceptedVersion: 1 (or null, which defaults to v1) — go back and fix it.
Hit a Flux endpoint:
curl -H "Authorization: Bearer $TOKEN" https://flux.example.com/workflows
Flux logs Auto-provisioned principal <sub> on first sign-in (when default_user_roles is set) or OIDC token validation failed: Invalid audience / … Invalid issuer on misconfiguration.
See Configuring OIDC for the four required claims, the deprecation of roles_claim, and how Flux resolves principals from (sub, iss).
Derived against Microsoft Entra docs 2026-05.