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.
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
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.
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
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.
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:
| Field | Value |
|---|---|
| Name | groups |
| Display phrase | groups |
| Include in public metadata | checked |
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"
| Parameter | What it does |
|---|---|
user_claim | Field used as the Vault username — sub is Okta’s unique user ID |
groups_claim | Field containing group membership, used to map to a Vault policy |
bound_audiences | Security 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_uris | Must match exactly what’s registered in the Okta app |
policies | Vault policy to assign on successful login |
token_ttl | How 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_ttlis 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_ttlshort — 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
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
| Error | Cause | Fix |
|---|---|---|
| One or more scopes are not configured | groups scope missing from the authorization server | Security → API → Authorization Servers → default → Scopes → add groups |
| User is not assigned to the client application | Authorization server access policy doesn’t include the Vault app | Check Okta system log for the exact reason — usually a missing access policy rule |
| Redirect URI mismatch | URI in the Vault role doesn’t match what’s registered in Okta | Ensure both callback URIs are registered in Okta and in the role — exact match required |
| No permissions after login | Policy name in the role doesn’t match an existing policy | Run 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.
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_audiencesis a security control that prevents tokens issued for other apps from being reused against Vault — don’t skip it- The
groupsscope 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
