Last updated: August 2026
HashiCorp Vault supports OIDC login through its built-in OIDC auth method, which lets you point Vault at your Keycloak realm’s discovery URL and delegate all identity decisions to Keycloak. You register Vault as a confidential OIDC client in your Keycloak realm with two specific redirect URIs, one for the browser UI callback and one for the CLI’s localhost callback, then add a groups protocol mapper so Vault can read group membership from the token and automatically assign policies. The result is a fully SSO-enabled Vault deployment where engineers log in with their company Keycloak credentials and inherit the right permissions without any manual Vault user management.
If your team already uses Keycloak for SSO, extending that to Vault is one of the highest-leverage things you can do. It eliminates a separate set of Vault usernames and passwords, centralises access in the identity layer you already manage, and gives you Keycloak’s audit trail for every Vault login. This tutorial walks through the complete configuration from scratch: enabling the auth method, creating the Keycloak client, wiring up the groups claim, creating the Vault role, mapping groups to policies, and verifying login through both the UI and the CLI. For a broader view of how SSO fits into a mature identity architecture, see our SSO implementation guide for developers.
How Vault’s OIDC auth method works
Before touching any configuration, it helps to understand what Vault’s OIDC auth method actually does. When a user initiates a login, Vault redirects their browser to Keycloak’s authorization endpoint. Keycloak authenticates the user, issues an ID token and access token, and redirects back to Vault’s callback URL. Vault validates the token signature against Keycloak’s JWKS endpoint (discovered automatically via the realm’s .well-known/openid-configuration URL), extracts the claims you specify, typically sub for the user identity and a custom groups claim for group membership, and maps those claims to Vault policies.
The OIDC auth method is a superset of Vault’s JWT auth method. Both use the same underlying auth/jwt plugin path; the difference is that OIDC uses the browser-based redirect flow while JWT validates a bearer token directly. This tutorial uses the OIDC flow, which is the right choice for interactive human login. For machine-to-machine scenarios (CI/CD pipelines, for example), the JWT method with a Keycloak service account token is a better fit, but that is a separate topic.
Understanding the protocol at this level matters because the most common configuration errors, redirect URI mismatches, missing claims, policy binding failures, all stem from a gap between what Vault expects and what Keycloak sends. The sections below are ordered to eliminate each failure point in turn. If you are new to OIDC itself, our OpenID Connect explainer for developers covers the token flow in depth.
Prerequisites
- A running Keycloak 26.x instance. The realm discovery URL follows the pattern
https://<keycloak-host>/realms/<realm-name>. - A Vault cluster (any edition, 1.13+). You need
vaultCLI access with a token that hasauth/mount permissions. - The Keycloak realm where your engineers already have accounts, or a dedicated realm for infrastructure access.
- Network connectivity between the Vault server and Keycloak (Vault fetches the JWKS endpoint server-side during token validation).
Step 1, Enable the OIDC auth method in Vault
Vault ships with the OIDC/JWT auth method available but not mounted. Enable it at the default path:
vault auth enable oidc
If you prefer a custom mount path (for example, to run multiple OIDC providers simultaneously), specify it with -path:
vault auth enable -path=keycloak oidc
This tutorial uses the default oidc path throughout. Adjust the auth/oidc/ prefix in every subsequent command if you chose a custom path.
Step 2, Create the Keycloak OIDC client
In the Keycloak Admin Console, navigate to your realm and open Clients > Create client.
Basic settings
| Field | Value |
|---|---|
| Client type | OpenID Connect |
| Client ID | vault (or any identifier you choose, you will reference this in Vault config) |
| Name | HashiCorp Vault |
Click Next.
Capability config
| Field | Value |
|---|---|
| Client authentication | On (this makes the client confidential) |
| Authorization | Off |
| Standard flow | Enabled |
| Direct access grants | Disabled |
Confidential clients send a client_secret along with every token request, which Vault supports and which is required for server-to-server token validation. Public clients are not appropriate here.
Login settings, the two redirect URIs
This is the step that causes the most friction. Vault needs two redirect URIs registered in Keycloak:
- UI callback: for browser-based login through the Vault web interface:
https://<vault-host>:8200/ui/vault/auth/oidc/oidc/callback - CLI callback: for
vault login -method=oidcfrom the terminal, which spins up a temporary local HTTP server:http://localhost:8250/oidc/callback
Add both to the Valid redirect URIs field. If you skip the CLI URI, the vault login -method=oidc command will fail with a redirect_uri_mismatch error even though the UI login works fine. If you skip the UI URI, the browser flow breaks. Both are required for full functionality.
Also set Web origins to + (which tells Keycloak to allow CORS from any redirect URI origin) or to the explicit Vault hostname if you want tighter control.
Save the client. Then open the Credentials tab and copy the Client secret: you will need it in Step 4.
Step 3, Add the groups protocol mapper
By default, Keycloak does not include group membership in the ID token. You need to add a protocol mapper that injects a groups claim. This is the mechanism Vault uses to determine which policies to assign.
In the Keycloak Admin Console, open the vault client you just created. Navigate to Client scopes and click the dedicated client scope that was auto-created (it follows the pattern vault-dedicated). Inside that scope, go to Mappers > Add mapper > By configuration, then select Group Membership.
Configure the mapper:
| Field | Value |
|---|---|
| Name | groups |
| Token claim name | groups |
| Full group path | Off (send just the group name, not /engineering/backend) |
| Add to ID token | On |
| Add to access token | On |
| Add to userinfo | On |
The Full group path setting matters. If you enable it, the claim value is /vault-admins instead of vault-admins. Vault’s groups_claim matching works against the raw string, so you need to know which format to expect and configure your external group aliases accordingly. Keeping it off (short names) is simpler for most setups.
Understanding how Keycloak scopes and claims interact in more detail is covered in our post on Keycloak client scopes vs. roles explained.
Alternative: use roles instead of groups
If your organisation models access via Keycloak realm roles or client roles rather than groups, you can use the User Realm Role or User Client Role mapper instead, with a token claim name of roles (or any name you choose), and then set groups_claim to roles in the Vault role configuration. The principle is the same: pick a claim name, add the mapper, and reference that claim name consistently in Vault.
Step 4, Configure Vault’s OIDC auth method
With the Keycloak client created and the client secret in hand, configure the auth method:
vault write auth/oidc/config
oidc_discovery_url="https://<keycloak-host>/realms/<realm-name>"
oidc_client_id="vault"
oidc_client_secret="<paste-client-secret-here>"
default_role="default"
The oidc_discovery_url points Vault at the realm’s well-known configuration endpoint. Vault appends /.well-known/openid-configuration automatically to discover the authorization endpoint, token endpoint, and JWKS URI. You never need to specify those individually.
default_role sets which role Vault uses when a user logs in without specifying one. You will create this role in the next step.
Step 5, Create the Vault OIDC role
A Vault OIDC role ties together the claim mappings, policy assignments, and allowed redirect URIs. Create a default role that applies to all Keycloak users, with policy assignment driven by the groups claim:
vault write auth/oidc/role/default
bound_audiences="vault"
user_claim="sub"
groups_claim="groups"
allowed_redirect_uris="https://<vault-host>:8200/ui/vault/auth/oidc/oidc/callback,http://localhost:8250/oidc/callback"
token_policies="default"
token_ttl="1h"
token_max_ttl="4h"
Key parameters explained:
bound_audiences, must match theaudclaim in the token. Keycloak sets this to the client ID (vault), so this value must match.user_claim, the claim Vault uses as the local entity alias.sub(the Keycloak user UUID) is the most stable choice. Avoidpreferred_usernamesince usernames can change.groups_claim, the claim name you set in the Keycloak mapper. Must match exactly.allowed_redirect_uris, the same two URIs you registered in Keycloak. Vault validates the redirect URI on every login attempt; mismatches cause immediate failures.token_policies, baseline policies every authenticated user gets.defaultis a built-in Vault policy with minimal read permissions.
The groups_claim is what enables dynamic policy assignment per group without creating individual role entries per team. Vault reads the claim value as a list of group names and looks for matching external group aliases to determine additional policies.
Step 6, Map Keycloak groups to Vault policies
This step is the most operationally significant: it determines which Vault paths each Keycloak group can access. The mechanism is Vault’s external groups with group aliases pointing at the OIDC auth method.
First, identify the accessor of the OIDC auth method (you need it to create the alias):
vault auth list -format=json | jq -r '.["oidc/"].accessor'
Save that accessor string. Now, for each Keycloak group you want to map, create an external group in Vault and bind a policy to it:
# Create the external group for vault-admins
vault write identity/group
name="vault-admins"
type="external"
policies="vault-admin-policy"
# Capture the group ID
GROUP_ID=$(vault read -field=id identity/group/name/vault-admins)
# Create the group alias linking the group name to the OIDC accessor
vault write identity/group-alias
name="vault-admins"
canonical_id="$GROUP_ID"
mount_accessor="<oidc-accessor>"
The name in the group alias must exactly match the value that will appear in the groups claim token. If your Keycloak group is named vault-admins, the alias name must be vault-admins.
Repeat this pattern for every group you want to map. A typical mapping table looks like this:
| Keycloak Group | Vault External Group | Vault Policy | Access Level |
|---|---|---|---|
vault-admins |
vault-admins |
vault-admin-policy |
Full read/write on all paths |
vault-ops |
vault-ops |
vault-ops-policy |
Read/write on secret/ops/* |
vault-dev |
vault-dev |
vault-dev-policy |
Read on secret/dev/* |
vault-readonly |
vault-readonly |
vault-readonly-policy |
Read on secret/shared/* |
For the access control model to make sense, each policy should be a Vault HCL policy file stored in version control and applied with vault policy write. For example, vault-dev-policy.hcl:
path "secret/data/dev/*" {
capabilities = ["read", "list"]
}
path "secret/metadata/dev/*" {
capabilities = ["list"]
}
Apply it:
vault policy write vault-dev-policy vault-dev-policy.hcl
This role-based policy structure maps closely to the principle of least privilege. For a deeper treatment of role-based access control design, see our guide on RBAC and protecting digital access.
Step 7, Log in via the Vault UI
Open https://<vault-host>:8200/ui. On the login screen, select OIDC from the method dropdown. Leave the role field as default (or specify a role name if you created multiple roles). Click Sign in with OIDC Provider.
Keycloak’s login page opens in the same browser window. The user authenticates with their standard Keycloak credentials. On success, Keycloak redirects to https://<vault-host>:8200/ui/vault/auth/oidc/oidc/callback with the authorization code. Vault exchanges the code for tokens, validates the ID token, reads the groups claim, and resolves the applicable group aliases. The user lands in the Vault UI with the policies their group memberships entitle them to.
Step 8, Log in via the Vault CLI
The CLI flow uses a browser redirect to a localhost callback. From a terminal with the vault binary and VAULT_ADDR set:
vault login -method=oidc role=default
Vault prints a URL and opens it in your default browser. You authenticate with Keycloak in the browser. Keycloak redirects to http://localhost:8250/oidc/callback, a temporary HTTP server that vault login spins up on port 8250. Vault captures the code, completes the token exchange, and prints a Vault token to the terminal:
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token hvs.CAES...
token_accessor abc123...
token_duration 1h
token_renewable true
token_policies ["default" "vault-dev-policy"]
identity_policies []
policies ["default" "vault-dev-policy"]
token_meta_role default
The token_policies line shows both the baseline default policy and the group-derived vault-dev-policy, confirming that group claim mapping worked correctly.
This OIDC-based login pattern integrates naturally with a broader identity brokering architecture. If you are federating multiple identity providers into Keycloak before forwarding to Vault, see our guide on Keycloak identity brokering with GitHub social login for an example of adding upstream providers.
Troubleshooting common issues
Redirect URI mismatch
Symptom: Keycloak returns invalid_redirect_uri or redirect_uri_mismatch. Vault may show a generic OIDC callback error.
Cause: The URI Vault sends in the authorization request does not exactly match any URI in the Keycloak client’s Valid redirect URIs list. This is almost always a trailing slash, HTTP vs HTTPS, or port number discrepancy.
Fix: In the Keycloak Admin Console, open the vault client and compare the Valid redirect URIs field against the allowed_redirect_uris value in your Vault role. They must be byte-for-byte identical.
Groups claim not present in token
Symptom: Login succeeds but the user only gets the default policy, group-based policies are not applied.
Cause: The groups mapper is not configured correctly, or it is attached to a scope that is not included in the token by default.
Fix: In Keycloak, use the Evaluate tab under the vault client’s Client scopes section to simulate a token for a test user. Look for the groups claim in the decoded ID token. If it is absent, check that the mapper is attached to the vault-dedicated scope (not a separate optional scope that Vault is not requesting). Also verify that Add to ID token is enabled on the mapper.
Group alias name mismatch
Symptom: The groups claim is visible in the token (confirmed via Evaluate), but Vault still does not apply group policies.
Cause: The group alias name in Vault does not exactly match the string value in the token. This often happens when Full group path is enabled in the mapper (sending /vault-admins) but the alias is named vault-admins.
Fix: Decode a real ID token from a login attempt (use the JWT Token Analyzer to inspect the raw claims) and confirm the exact string value of each entry in the groups array. Update the Vault group alias name to match.
Port 8250 not reachable for CLI login
Symptom: vault login -method=oidc hangs or returns unable to start local HTTP server.
Cause: Port 8250 is blocked by a firewall or already in use. The vault login command must be able to bind localhost:8250.
Fix: Use -port to specify an alternate port, and add the corresponding http://localhost:<port>/oidc/callback URI to both the Keycloak client’s Valid redirect URIs and the Vault role’s allowed_redirect_uris.
Frequently asked questions
How do I set up Vault SSO with Keycloak?
Enable the OIDC auth method in Vault with vault auth enable oidc, then configure it with vault write auth/oidc/config pointing oidc_discovery_url at your Keycloak realm URL (https://<keycloak-host>/realms/<realm-name>). Create a confidential Keycloak client with both the UI and CLI redirect URIs registered, copy the client secret into the Vault config, and create a Vault OIDC role that maps the groups claim. Users can then log in at the Vault UI by selecting OIDC, or from the terminal with vault login -method=oidc.
How do I map Keycloak groups to Vault policies?
Add a Group Membership protocol mapper to the Keycloak vault client so the ID token carries a groups claim. In Vault, create external identity groups (vault write identity/group ... type=external policies=<policy-name>), then create group aliases that link each group name to the OIDC auth method’s accessor (vault write identity/group-alias name=<keycloak-group-name> mount_accessor=<oidc-accessor>). When a user logs in, Vault reads the groups claim, finds matching aliases, and applies the bound policies automatically.
What redirect URIs does Vault need for OIDC?
Vault requires two redirect URIs registered in Keycloak. The first is the UI callback: https://<vault-host>:8200/ui/vault/auth/oidc/oidc/callback. The second is the CLI callback: http://localhost:8250/oidc/callback. Both must be listed in the Keycloak client’s Valid redirect URIs and in the Vault role’s allowed_redirect_uris. Missing either one causes authentication failures for that specific login method.
Can I use Keycloak realm roles instead of groups for Vault policy mapping?
Yes. Add a User Realm Role mapper to the Keycloak client with a token claim name of roles (or any name), then set groups_claim="roles" in the Vault OIDC role. Create Vault external groups and aliases using the realm role names instead of group names. The alias lookup works the same way regardless of whether the claim carries group names or role names.
How do I verify the groups claim is being sent correctly?
In the Keycloak Admin Console, open the vault client, navigate to Client scopes, click the Evaluate tab, enter a test username, and click Generated ID token. Inspect the decoded JSON for the groups key and its values. You can also decode a live ID token using the JWT Token Analyzer at any point after a real login attempt.
Conclusion
Connecting HashiCorp Vault to Keycloak via OIDC is a three-layer configuration: the Keycloak client (with both redirect URIs and the groups mapper), the Vault auth method config (pointing at the realm discovery URL), and the Vault role and external group aliases (wiring the groups claim to policies). The trickiest part is keeping the redirect URIs and the groups claim name consistent across all three layers, the troubleshooting section above covers the failure modes you are most likely to encounter.
Once the integration is in place, every engineer who already has a Keycloak account can log into Vault without a separate credential. Group membership changes in Keycloak propagate to Vault on the next login, with no manual Vault user management required. The audit trail for every Vault login is visible in Keycloak’s event log alongside all other authentication events.
If you are running Keycloak yourself, the operational overhead of keeping it patched, scaled, and highly available can be significant. Skycloak provides managed Keycloak hosting with automatic updates, high availability, and pre-configured OIDC client templates, so you can focus on integrating Vault rather than operating Keycloak.