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”:

  1. 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.
  2. Token version setting. This is the critical Entra-specific step. In the app’s Manifest, set:

    "accessTokenAcceptedVersion": 2

    Without this, Entra issues v1 access tokens with the v1 issuer (https://sts.windows.net/<tenant>/) and v1 claim shapes (aud is often the resource URI rather than the client ID; oid instead of sub for 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:

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

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:

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:

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.