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.
Auth method configuration replicates automatically across Raft cluster nodes. Configure OIDC once and it’s available everywhere — no need to repeat setup on each node.
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
# Full access to KV secrets
path "secret/*" {
capabilities = ["create", "read", "update", "patch", "delete", "list"]
}
# Read-only access to sys endpoints
path "sys/*" {
capabilities = ["read", "list"]
}
# Manage auth methods and policies
path "sys/auth/*" {
capabilities = ["create", "read", "update", "delete", "sudo"]
}
EOF
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.
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.
Step 3 — Add the Groups Scope to the Authorization Server
This is the step that most causes 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, 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 | Only accept tokens issued for this specific client ID — prevents tokens from other apps being reused here |
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 |
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, that policy should be stricter than most.
- Require MFA for every session — password alone is not appropriate for Vault access. Use WebAuthn, Okta Verify FastPass, or TOTP
- Require re-authentication per session — don’t allow an extended Okta session window to substitute for fresh authentication
- Network restrictions — if Vault is internal only, restrict the Okta app to known network zones
- Keep token_ttl short — the Vault token TTL is a second layer of time-limiting on top of Okta’s session policy
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 |
Key Points
- Use OIDC, not the native Okta auth method — it’s the modern standard and doesn’t require an Okta API token in your Vault config
- 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 — it prevents tokens issued for other apps from being reused to authenticate to Vault- The
groupsscope must exist on the authorization server, not just as a claim — Vault explicitly requests it and Okta will reject the flow if it’s missing - Policy names don’t need to match Okta group names — the role configuration is where that mapping happens
- Root token should be stored offline and used only for break-glass situations — day-to-day access should go through OIDC
