Okta
Wiring Okta as Flux's OIDC identity provider — authorization servers, audience handling, and the minimal Flux config.
Okta is a hosted OIDC provider built around the concept of authorization servers: each one has its own issuer URL, audience, and signing keys. Flux talks to Okta the same way it talks to any other OIDC IdP: discovery, JWKS, RS256-signed access tokens. But you need to pick the right authorization server and audience before tokens will validate. The abstract Flux contract is in Configuring OIDC; this page covers the Okta-specific steps.
What to register at Okta
You need an authorization server and an application:
- Authorization server. Okta provisions a
defaultCustom Authorization Server in every Okta org. Its URL ishttps://<your-domain>.okta.com/oauth2/defaultand its default audience isapi://default. For production, create a dedicated authorization server per environment (flux-prod,flux-staging) so issuer URLs and audiences are not shared across deployments. - Application. Use API Services (the OIDC client_credentials variant) for server-to-server flows: workers, CI jobs, anything that gets a token via the client-credentials grant. Use Web Application for browser flows. Either way, grant the app access to your authorization server.
The audience field in Flux must match the authorization server’s audience exactly (api://default by default, or whatever you set when creating a custom server). The issuer field is the authorization server URL (no trailing slash).
Confirm the signing algorithm on the authorization server is RS256 — that is the default. Okta supports ES256 too; Flux accepts both.
Vendor-specific gotchas
- Issuer URL must include the
/oauth2/<authServerId>segment. A barehttps://<your-domain>.okta.comis not a valid OIDC issuer for an authorization-server-backed token; discovery at that URL points to the Okta org-level metadata, not your authorization server. Flux will fail to find matching keys for tokens issued by a Custom Authorization Server. - Two issuer flavors. Okta has an “Okta URL” issuer style (
https://<domain>.okta.com/oauth2/default) and a “custom URL” style (your CNAME). Whichever you pick in the authorization server’s settings is what Okta stamps intoiss; Flux must be configured to match. - Groups in tokens. Okta returns a
groupsclaim if you add a groups claim filter to the access-token claims. Flux does not read this —roles_claimis deprecated, and roles come from Flux’s principals registry, not the token. Groups can still be useful for auto-provisioning logic outside Flux (e.g., a sync job that mirrors Okta groups into Flux roles). subvsuidvscid. For user tokens,subis the Okta user ID. For client-credentials tokens (API Services apps),subis the client ID. Both work with Flux’s principal lookup, but they are different namespaces — you may want to register them under different prefixes influx principals.- Token lifetime. Okta’s defaults are 1 hour for access tokens. Tune in the authorization server’s access policy.
- Default scopes. Okta requires at least one scope per token. Configure scopes on the authorization server and request them in the token endpoint call. Flux does not enforce scopes itself — they are purely for shaping what claims Okta includes.
The minimal Flux config
[flux.security.auth.oidc]
enabled = true
issuer = "https://your-domain.okta.com/oauth2/default"
audience = "api://default"
default_user_roles = ["viewer"]
Substitute your Okta domain and, if you created a custom authorization server, its ID and audience. The default_user_roles = ["viewer"] line opts into auto-provisioning on first sign-in; without it, unknown subjects get a Principal not provisioned 401. Set it to [] (or omit it) if you prefer to register every principal up-front via flux principals create.
jwks_cache_ttl = 3600 and clock_skew = 30 are the defaults and rarely need changing.
Verification
Pull the discovery document for your authorization server:
curl -s https://your-domain.okta.com/oauth2/default/.well-known/openid-configuration | jq .
Confirm:
issuermatches your Flux config exactly (no trailing slash on Okta’s side).id_token_signing_alg_values_supportedcontainsRS256(orES256).jwks_uriis reachable from the Flux host.
Smoke-test a client-credentials token (API Services app):
curl -s --request POST https://your-domain.okta.com/oauth2/default/v1/token \
--header 'Accept: application/json' \
--header 'Authorization: Basic <base64(client_id:client_secret)>' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data 'grant_type=client_credentials&scope=flux.read' \
| jq -r .access_token
Decode the payload and check iss, aud, exp, sub are all present. Hit Flux with it:
curl -H "Authorization: Bearer $TOKEN" https://flux.example.com/workflows
Look in the Flux server logs for Auto-provisioned principal <sub> on first sign-in, or OIDC token validation failed: Invalid audience if the authorization server’s audience does not match your config.
See Configuring OIDC for the four required claims, the deprecation of roles_claim, and the Flux principal-resolution flow.
Derived against Okta docs 2026-05.