Vault OIDC Auth with Okta

← All guides

Vault OIDC Auth with Okta

Vault’s default authentication model is root tokens and static admin tokens. Neither expires automatically, neither requires MFA, and neither connects to your identity governance program. In an audit, long-lived privileged credentials with no rotation schedule and no MFA requirement are IA-5 and IA-2(1) findings. In a real offboarding scenario, they’re access that survives termination until someone manually hunts down every token that person held.

OIDC replaces that model entirely. Tokens are time-limited, MFA is enforced through Okta’s authentication policy, and disabling a user in Okta is the only revocation action needed.

Vault ships with two ways to authenticate with Okta: a dedicated Okta auth method that calls the Okta API directly, and OIDC — the standard OAuth2/OpenID Connect flow. This post covers OIDC. It’s the modern recommended approach, it’s consistent with how Kubernetes OIDC authentication works, and it doesn’t require an Okta API token sitting in your Vault config.

The end state: users run vault login -method=oidc, complete their Okta login in the browser, and get a Vault token scoped to their group’s policy. Disable the user in Okta and they lose access immediately — no tokens to hunt down.

Raft cluster note

This configuration replicates automatically across Raft if run clustered.

Step 1 — Write the Vault Policy

Create the policy before configuring the auth method. The policy name doesn’t need to match the Okta group name — the role configuration is where that mapping happens.

vault policy write admin - <<EOF
path "*" {
  capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}
EOF
Lab-scoped policy

This grants full access to every path in Vault — fine for demonstrating the OIDC flow, but not appropriate for production. In a real environment, scope this policy to the specific paths your admin group actually needs (e.g. secret/data/*, sys/policies/*) rather than the wildcard shown here.

Check what’s already there

Before writing policies, audit your existing Vault instance to avoid conflicts with pre-existing engines or auth methods.

vault auth list
vault policy list
vault secrets list

Step 2 — Create the Okta App

Create a dedicated app for Vault — separate from any Kubernetes OIDC app — so access policies and audit logs stay clean. Mixing them makes it harder to apply app-specific authentication policies and harder to trace access in the Okta system log.

Applications → Create App Integration:

  • Sign-in method: OIDC – OpenID Connect
  • Application type: Web Application
Web Application vs Native

Vault uses a Web Application with a client secret, not a Native app with PKCE. Vault runs server-side and can safely store a secret.

Sign-in redirect URIs — both are required:

https://vault.yourdomain.com:8200/ui/vault/auth/oidc/oidc/callback
http://localhost:8250/oidc/callback

The first handles browser UI login. The second handles vault login -method=oidc from the terminal, which spins up a local listener to catch the callback.

Set Assignments to limit access to your admin group. Don’t leave this open to the entire org.

Step 3 — Add the Groups Scope to the Authorization Server

This is the step most likely to cause trouble when coming from a Kubernetes OIDC setup. Kubernetes reads whatever claims come back in the token without explicitly requesting them. Vault explicitly requests groups as a scope — if that scope doesn’t exist on the authorization server, Okta rejects the request entirely.

Scope vs claim

A scope is what the app asks Okta for permission to include. A claim is the actual data in the returned token. The groups claim may already be configured and working for Kubernetes, but Vault needs the groups scope to also exist before it can request it.

Security → API → Authorization Servers → default → Scopes → Add Scope:

FieldValue
Namegroups
Display phrasegroups
Include in public metadatachecked

Also add the Vault app to your authorization server access policy, or create a dedicated one for it.

Step 4 — Enable and Configure OIDC in Vault

vault auth enable oidc

vault write auth/oidc/config \
  oidc_discovery_url="https://auth.yourdomain.com/oauth2/default" \
  oidc_client_id="your-vault-app-client-id" \
  oidc_client_secret="your-client-secret" \
  default_role="default"

vault write auth/oidc/role/default \
  user_claim="sub" \
  groups_claim="groups" \
  oidc_scopes="openid,profile,email,groups" \
  bound_audiences="your-vault-client-id" \
  allowed_redirect_uris="https://vault.yourdomain.com:8200/ui/vault/auth/oidc/oidc/callback,http://localhost:8250/oidc/callback" \
  policies="admin" \
  token_ttl="2h"
ParameterWhat it does
user_claimField used as the Vault username — sub is Okta’s unique user ID
groups_claimField containing group membership, used to map to a Vault policy
bound_audiencesSecurity control — only accept tokens issued specifically for this Vault app’s client ID. Prevents tokens issued for other apps (Kubernetes, other services) from being reused to authenticate to Vault
allowed_redirect_urisMust match exactly what’s registered in the Okta app
policiesVault policy to assign on successful login
token_ttlHow long the resulting Vault token is valid — the session termination control

Step 5 — Test

CLI login

vault login -method=oidc

Opens a browser, completes Okta authentication, writes the resulting token to the local token helper. After this, normal Vault commands work for the duration of the TTL.

UI login

Navigate to the Vault UI and select OIDC from the auth method dropdown on the login screen.

Verify permissions

vault token lookup
vault token capabilities secret/data/test

Authentication Policy Considerations

OIDC works within Okta’s authentication policies, not around them. Before Okta issues a token to Vault, the user must pass the authentication policy on the Vault app. Given that Vault holds secrets, credentials, and signing keys for your entire infrastructure, the authentication policy here should be stricter than most applications in your environment.

  • Require MFA for every session — password alone is not appropriate for Vault access. Use WebAuthn, Okta Verify FastPass, or TOTP. This is IA-2(1) for privileged access and is the single most impactful control this integration enables
  • Require re-authentication per session — don’t allow an extended Okta session window to substitute for fresh authentication. Vault access warrants its own session boundary, and token_ttl is the AC-12 session termination control on the Vault side
  • Network restrictions — if Vault is internal only, restrict the Okta app to known network zones so authentication requests from outside your environment are rejected before a token is even considered
  • Keep token_ttl short — the Vault token TTL is a second layer of time-limiting on top of Okta’s session policy. Two hours is a reasonable starting point for interactive access
Three Okta checks

Every Vault OIDC login goes through three separate Okta gates: app assignment, authentication policy, and authorization server access policy. All three must pass. The Okta system log identifies which one is failing when something goes wrong.

Troubleshooting

ErrorCauseFix
One or more scopes are not configuredgroups scope missing from the authorization serverSecurity → API → Authorization Servers → default → Scopes → add groups
User is not assigned to the client applicationAuthorization server access policy doesn’t include the Vault appCheck Okta system log for the exact reason — usually a missing access policy rule
Redirect URI mismatchURI in the Vault role doesn’t match what’s registered in OktaEnsure both callback URIs are registered in Okta and in the role — exact match required
No permissions after loginPolicy name in the role doesn’t match an existing policyRun vault policy list and verify the name matches exactly

Control Mapping

Replacing static Vault tokens with OIDC-based authentication connects Vault access to your identity governance program. The controls it satisfies address gaps that token-based access management cannot close.

NIST IA-2 NIST IA-5 NIST AC-2 NIST AC-12 NIST AU-2 NIST AU-12

IA-2 (Identification and Authentication — Organizational Users) requires unique identification and authentication, with IA-2(1) requiring MFA for privileged access. Vault is privileged infrastructure — it holds credentials for everything else in your environment. Requiring MFA through the Okta authentication policy before a token is issued satisfies IA-2(1) in a way that static token distribution fundamentally cannot.

IA-5 (Authenticator Management) covers the lifecycle of authentication credentials. A root token or long-lived admin token distributed via password manager is an IA-5 finding: no expiration, no rotation requirement, and no record of who currently holds it. OIDC-issued tokens are time-limited by design and tied to a live Okta identity. The root token should be stored offline and used only for break-glass situations — that’s the IA-5 compliant posture for an emergency credential.

AC-2 (Account Management) requires that access is revoked when no longer needed. With static tokens, revoking access requires knowing every token a person holds and explicitly revoking each one. With OIDC, disabling the Okta account is the single revocation action — the next token request is rejected before it reaches Vault regardless of what tokens may still be cached.

AC-12 (Session Termination) requires that sessions are terminated after a defined time period. The token_ttl parameter is the implementation of AC-12 for Vault sessions — it sets a hard expiration on the token regardless of activity. Setting a tighter TTL for Vault than for general applications is a defensible and documented AC-12 decision.

AU-2 and AU-12 (Audit Events and Audit Record Generation) require that authentication events are logged with sufficient identity detail. Vault’s audit log captures every login, every secret read, and every policy change. With OIDC, the identity in that log is the Okta sub — a unique, attributable user identifier. Static token audit logs show a token accessor, which tells you what happened but not necessarily who did it without additional correlation work.

Key Points

  • Use OIDC over the native Okta auth method — it’s the modern standard and doesn’t require an Okta API token in your Vault config
  • Create a separate Okta app for Vault rather than reusing the Kubernetes one — clean audit logs and app-specific authentication policies are worth the extra setup
  • Both redirect URIs are required — one for the UI, one for CLI. Both must be registered in Okta and in the role
  • bound_audiences is a security control that prevents tokens issued for other apps from being reused against Vault — don’t skip it
  • The groups scope must exist on the authorization server, not just as a claim — Vault explicitly requests it and Okta rejects the flow if it’s missing
  • Configure MFA in the Okta authentication policy — this is IA-2(1) and is the most impactful single control this integration enables
  • Root token belongs offline in a break-glass procedure, not in a password manager for day-to-day use — storing it that way is an IA-5 and SC-12 finding

Tags:

Darnell Keith

Not sure where you stand on this?

A Gap Assessment or IAM Governance Assessment tells you exactly where the gaps are — and what to do about them, in order of what matters most.

Get in Touch
NAXS Labs
Logo