Secure workflows with OIDC authentication
Before a client can interact with Vault, it must authenticate with an auth method to acquire a token. This token has policies attached so that the behavior of the client can be governed.
NOTE: To learn the basics of Vault tokens, go through the Tokens tutorial.
Auth methods perform authentication to verify the user or machine-supplied information. Some of the supported auth methods are targeted towards users while others are targeted toward machines or apps.
Challenge
Vault supports a number of auth methods for users or system to prove their identity so that a token with appropriate policies can be obtained. Delegated authorization methods based on OAuth 2.0 are convenient for users and have become increasingly common, but the identity semantics are vague and vary between providers.
Solution
Vault supports OpenID Connect (OIDC). OIDC provides an identity layer on top of OAuth 2.0 to address the shortcomings of using OAuth 2.0 for establishing identity. The OIDC auth method allows a user's browser to be redirected to a configured identity provider, complete login, and then be routed back to Vault's UI with a newly-created Vault token.
This method is familiar for most users. For operators, the types of identity data that can be provided as part of OIDC allow for flexible mapping to Vault's identity system.
Prerequisites
To perform the tasks described in this tutorial, you need to have a Vault 1.1 or later. Refer to the Vault install guide to install Vault. Make sure that your Vault server has been initialized and unsealed.
Auth0 Account
To demonstrate an end-to-end workflow, this tutorial uses Auth0, so create an account if you don't have one.
Note
This tutorial uses Auth0. Some settings in this tutorial may be specific to Auth0. If you prefer to try the OIDC auth method using Google OAuth, refer to Vault OpenID Demo. For other provider configuration steps, refer to the OIDC Provider Setup documentation.
Policy requirements
Note
For the purpose of this tutorial, you can use the root
token to
work with Vault. However, it is recommended that root tokens are only used for
just enough initial setup or in emergencies. As a best practice, use tokens with
an appropriate set of policies based on your role in the organization.
To perform all tasks demonstrated in this tutorial, your policy must include the following permissions:
# Mount the OIDC auth method
path "sys/auth/oidc" {
capabilities = [ "create", "read", "update", "delete", "sudo" ]
}
# Configure the OIDC auth method
path "auth/oidc/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Write ACL policies
path "sys/policies/acl/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# List available secrets engines to retrieve accessor ID
path "sys/mounts" {
capabilities = [ "read" ]
}
If you are not familiar with policies, complete the policies tutorial.
Note
If you receive any errors following this tutorial, please review the Troubleshooting section.
Lab Setup
In another terminal, start a Vault dev server with
root
as the root token.$ vault server -dev -dev-root-token-id root
The Vault dev server defaults to running at
127.0.0.1:8200
. The server is initialized and unsealed.Insecure operation
Do not run a Vault dev server in production. This approach starts a Vault server with an in-memory database and runs in an insecure way.
Export an environment variable for the
vault
CLI to address the Vault server.$ export VAULT_ADDR=http://127.0.0.1:8200
Export an environment variable for the
vault
CLI to address the Vault server through the OIDC interface.$ export VAULT_OIDC_ADDR=http://127.0.0.1:8250
Export an environment variable for the
vault
CLI to authenticate with the Vault server.$ export VAULT_TOKEN=root
Note
For these tasks, you can use Vault's root token. However, it is recommended that root tokens are only used for enough initial setup or in emergencies. As a best practice, use an authentication method or token that meets the policy requirements.
The Vault server is ready.
Get Auth0 credentials
If you do not have an account with Auth0, sign up to create one first.
In the Auth0 dashboard, click Applications to expand the accordion menu and select Applications.
Click the ellipses for Default App and select Settings.
Copy the Domain.
In a terminal, set the variable
AUTH0_DOMAIN
to the Domain.$ export AUTH0_DOMAIN=<Domain>
Copy the Client ID.
In a terminal, set the variable
AUTH0_CLIENT_ID
to the Client ID.$ export AUTH0_CLIENT_ID=<Client ID>
Copy the Client Secret.
In a terminal, set the variable
AUTH0_CLIENT_SECRET
to the Client Secret.$ export AUTH0_CLIENT_SECRET=<Client Secret>
In the Allowed Callback URLs field, enter the URL for your Vault instance.
For example, if you are running Vault locally:
http://localhost:8250/oidc/callback, http://localhost:8200/ui/vault/auth/oidc/oidc/callback
The
http://localhost:8250/oidc/callback
address enables the Vault CLI to login via the OIDC method. Thehttp://localhost:8200/ui/vault/auth/oidc/oidc/callback
address enables the Vault web UI to login via the OIDC method.Note
The callback URLs must be comma-separated.
Scroll to to the bottom of the page and click Save Changes.
Create Vault policies
Within an organization personas with different capabilities are required to interact with the secrets stored in Vault. Each persona requires a different set of capabilities. These are expressed in policies. If you are not familiar with policies, complete the policies tutorial.
Create the policy file named
manager.hcl
.$ tee manager.hcl <<EOF # Manage k/v secrets path "/secret/*" { capabilities = ["create", "read", "update", "delete", "list"] } EOF
This policy grants most capabilities to all paths in KV secrets engine enabled at the
secret
path.Create the policy file named
reader.hcl
.$ tee reader.hcl <<EOF # Read permission on the k/v secrets path "/secret/*" { capabilities = ["read", "list"] } EOF
This policy grants
read
andlist
capabilities to all paths in the KV secrets engine enabled at thesecret
path.Create a policy named
manager
with the policy defined inmanager.hcl
.$ vault policy write manager manager.hcl
Create a policy named
reader
with the policy defined inreader.hcl
.$ vault policy write reader reader.hcl
List all the policies.
$ vault policy list default manager reader root
The
manager
andreader
policies are present in the list alongside the policies that Vault automatically creates.
Enable OIDC auth method
OIDC must be enabled and configured before it can be used.
Enable the
oidc
auth method at the default path.$ vault auth enable oidc
The OIDC auth method is enabled at the path
oidc
.Configure the
oidc
auth method.$ vault write auth/oidc/config \ oidc_discovery_url="https://$AUTH0_DOMAIN/" \ oidc_client_id="$AUTH0_CLIENT_ID" \ oidc_client_secret="$AUTH0_CLIENT_SECRET" \ default_role="reader"
The
oidc_discovery_url
,oidc_client_id
, andoidc_client_secret
are set to the variables defined in the Get Auth0 credentials step.The
default_role
is set toreader
. This is a role defined for the authentication method that assigns thereader
policy.Create the
reader
role.$ vault write auth/oidc/role/reader \ bound_audiences="$AUTH0_CLIENT_ID" \ allowed_redirect_uris="http://localhost:8200/ui/vault/auth/oidc/oidc/callback" \ allowed_redirect_uris="http://localhost:8250/oidc/callback" \ user_claim="sub" \ token_policies="reader"
The
allowed_redirect_uris
andallowed_redirect_uris
use the Allowed Callback URLs defined in the Get Auth0 credentials step. Theuser_claim
sets the claim to use to uniquely identify the user.
Login with OIDC
Log in with the
oidc
method as role of areader
.$ vault login -method=oidc role="reader"
When prompted, accept and authorize the Vault access to your Default App.
Note
Log into your Auth0 account with the same username and password that you used to configure Auth0 earlier in this tutorial.
Expected output looks like:
Complete the login via your OIDC provider. Launching browser to: https://dev-2i513orw.auth0.com/authorize?client_id=FFXlsY...snip... Waiting for OIDC authentication to complete... WARNING! The VAULT_TOKEN environment variable is set! The value of this variable will take precedence; if this is unwanted please unset VAULT_TOKEN or update its value accordingly. 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.CAESIGZPclnJZWNhvr8NqC_AQdmorQ5WUyh6TchZg9FUO89DGh4KHGh2cy5Bdm10ZERxUmNTcXdZUXhBdkZSMDF1dUs token_accessor 4Rb16tWG40xMaBSR2EUanUXD token_duration 768h token_renewable true token_policies ["default" "reader"] identity_policies [] policies ["default" "reader"] token_meta_role reader
Unauthorized Redirect URI Error
If you received unauthorized redirect_uri: redirect_uri=http://127.0.0.1:8250/oidc/callback
error, update the oidc
configuration for the reader
role.
Update the reader
role.
$ vault write auth/oidc/role/reader \
bound_audiences="$AUTH0_CLIENT_ID" \
allowed_redirect_uris="http://localhost:8200/ui/vault/auth/oidc/oidc/callback" \
allowed_redirect_uris="http://127.0.0.1:8250/oidc/callback" \
user_claim="sub" \
token_policies="reader"
The user logs in to Vault through OIDC with Auth0. The token issued to the user
is assigned through the reader
role which grants it the capabilities defined
in the reader
role.
Create an Auth0 group
A user that authenticates through OIDC with Auth0 may also have their Vault role assigned through metadata defined in Auth0.
In the Auth0 dashboard, select User Management > Users.
Click on your user name.
Enter the following metatada in the app_metadata text block.
{ "roles": ["kv-mgr"] }
When this user authenticates, this metadata is provided to Vault in the callback. Vault requests a token from the Vault group named
kv-mgr
.Click Save.
Click Action in the left navigation menu and select Flows.
Click Login then +
Select Build from scratch.
Enter
Set user role
in the Name field.Click on Create
Enter the following script in the Script field.
exports.onExecutePostLogin = async (event, api) => { if (event.authorization) { event.user.app_metadata = event.user.app_metadata || {}; api.idToken.setCustomClaim("https://example.com/roles",event.user.app_metadata.roles); } };
This script ensures that the user has the
app_metadata
field; creating one if none exists. Then assigns to thecontext.idToken
all the roles defined for the user; or an empty list if none exist.Click Deploy.
NOTE: The use of
example.com
is used here for demonstration.Click Back to flow.
Click the Custom tab, drag the
Set user role
Action to the Login flow, and then click Apply.For an extended details about creating and managing roles in Auth0, refer to the online documentation.
Create an external Vault group
A group claim is used to uniquely identify a set of groups to which the user belongs (this will be used as the names for the identity group aliases created after a successful login).
Note
If you are unfamiliar with Vault Identity, refer to the Identity: Entities and Groups tutorial.
Login as the
root
user.The Login with OIDC step has you authenticate with the capabilities of the
reader
policy. This token is unable to configure the OIDC auth method.$ vault login $VAULT_TOKEN
Create a role named
kv-mgr
.$ vault write auth/oidc/role/kv-mgr \ bound_audiences="$AUTH0_CLIENT_ID" \ allowed_redirect_uris="http://localhost:8200/ui/vault/auth/oidc/oidc/callback" \ allowed_redirect_uris="http://localhost:8250/oidc/callback" \ user_claim="sub" \ token_policies="reader" \ groups_claim="https://example.com/roles"
This role is defined similarly to the previously created role. The
reader
capability is assigned to the token. Additional policies are assigned through any groups that the user claims to belong. Thegroups_claim
field defines the value ofhttps://example.com/roles
. This value is the key in thecontext.idToken
that stores all the roles defined in the metadata for the user.Create an external group, named
manager
with themanager
policy.$ vault write identity/group name="manager" type="external" \ policies="manager" \ metadata=responsibility="Manage K/V Secrets"
Example output:
Key Value --- ----- id 1713c9c1-42c1-de6a-5d13-44f7c06f113f name manager
Create a variable named
GROUP_ID
to store theid
of themanager
group.$ GROUP_ID=$(vault read -field=id identity/group/name/manager)
Create a variable named
OIDC_AUTH_ACCESSOR
to store the accessor of theoidc
authentication method.$ OIDC_AUTH_ACCESSOR=$(vault auth list -format=json | jq -r '."oidc/".accessor')
This displays all authentication methods in JSON and then parses that list, through
jq
, to extract theaccessor
field of theoidc
authentication method.Create a group alias named
kv-mgr
.$ vault write identity/group-alias name="kv-mgr" \ mount_accessor="$OIDC_AUTH_ACCESSOR" \ canonical_id="$GROUP_ID"
The
kv-mgr
group alias connects theoidc
authentication method and themanager
group with themanager
policy.
Authenticate with kv-mgr role
With the kv-mgr
role configured, you can now authenticate and
have the manager
policy assigned from the group configuration.
Log in with the
oidc
method as role of akv-mgr
.$ vault login -method=oidc role="kv-mgr" Complete the login via your OIDC provider. Launching browser to: https://dev-2i513orw.auth0.com/authorize?client_id=FFXlsY2atr_wfNaF_hMtsE-zTAeTZnu8&nonce=5ad8af6eab5146d355ab5b25712b0d7776b384f7&redirect_uri=http%3A%2F%2Flocalhost%3A8250%2Foidc%2Fcallback&response_type=code&scope=openid&state=721184bf8d5abe295a617d1cb98ab75c1a7d39fc 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 s.WlmlH2yPid7sSKYbBlimD4MD token_accessor zd4MBqI9HD4YVhIWQKU6tz0b token_duration 768h token_renewable true token_policies ["default" "reader"] identity_policies ["manager"] policies ["default" "manager" "reader"] token_meta_role kv-mgr
The returned token inherits the
default
,manager
andreader
policies. Themanager
policy is assigned because the valuekv-mgr
, defined in the metadata, has an alias that belongs to themanager
group. Thereader
policy is assigned to thekv-mgr
role.
Leveraging Social Accounts
To enable your users login with their Google OAuth or any other social connections, click Marketplace > Social Connections from the Auth0 dashboard.
Click the tile for the integration you want to add and click the Add Integration button.
Follow the wizard for the selected integration, configuring the integration as needed and click the Create button.
Select your application under the Applications tab.
Any integrations you enabled will not be available when authenticating with Auth0.
NOTE: The client ID and client secret are unique to each application that you configured OIDC auth method with.
Troubleshooting
When configuring OIDC, configuration settings must be configured as documented, otherwise you may experience errors when authenticating. Below are some common error messages and how to troubleshoot them.
Error writing data to auth/oidc/config: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/auth/oidc/config
Code: 400. Errors:
* error checking oidc discovery URL: error creating provider with given values: NewProvider:
unable to create provider: oidc: issuer did not match the issuer returned by provider, expected
"https://example.auth0.com" got "https://example.auth0.com/"
Problem: This error can occur if domain being passed to the Vault configuration does not match the value returned by the provider.
Troubleshooting steps:
Check the Auth0 domain environment variable.
echo $AUTH0_DOMAIN
Verify it matches the client domain from the Auth0 admin portal.
If the value matches, verify the OIDC configuration passed to Vault is configured correctly.
$ vault write auth/oidc/config \ oidc_discovery_url="https://$AUTH0_DOMAIN/" \ oidc_client_id="$AUTH0_CLIENT_ID" \ oidc_client_secret="$AUTH0_CLIENT_SECRET" \ default_role="reader"
Error writing data to auth/oidc/config: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/auth/oidc/config
Code: 400. Errors:
* both 'oidc_client_id' and 'oidc_client_secret' must be set for OIDC
Problem: This error can occur if either the oidc_client_id
or oidc_client_secret
value is empty or null when passed to the Vault OIDC configuration.
Note
This error should not occur if the values are wrong - the configuration should still succeed.
Troubleshooting steps:
Check the
AUTH0_CLIENT_ID
andAUTH0_CLIENT_SECRET
environment variables.echo ID $AUTH0_CLIENT_ID "\n"SECRET $AUTH0_CLIENT_SECRET
Verify they match are not an empty value.
If the values are valid, verify the OIDC configuration passed to Vault are using the correct environment variables.
$ vault write auth/oidc/config \ oidc_discovery_url="https://$AUTH0_DOMAIN/" \ oidc_client_id="$AUTH0_CLIENT_ID" \ oidc_client_secret="$AUTH0_CLIENT_SECRET" \ default_role="reader"
Error authenticating: Error making API request.
URL: GET http://127.0.0.1:8200/v1/auth/oidc/oidc/callback?client_nonce=...snip...
Code: 400. Errors:
* Vault login failed. Error exchanging oidc code: "Provider.Exchange: unable to
exchange auth code with provider: oauth2: cannot fetch token: 401 Unauthorized\nResponse:
{\"error\":\"access_denied\",\"error_description\":\"Unauthorized\"}".
Problem: This error can occur if either the oidc_client_id
or oidc_client_secret
value does match the value from Auth0 when authenticating using the OIDC auth method.
Troubleshooting steps:
Check the
AUTH0_CLIENT_ID
andAUTH0_CLIENT_SECRET
environment variables.echo ID $AUTH0_CLIENT_ID "\n"SECRET $AUTH0_CLIENT_SECRET
Verify they match the values provided from the Auth0 portal.
If the values are valid, verify the OIDC configuration passed to Vault are using the correct environment variables.
$ vault write auth/oidc/config \ oidc_discovery_url="https://$AUTH0_DOMAIN/" \ oidc_client_id="$AUTH0_CLIENT_ID" \ oidc_client_secret="$AUTH0_CLIENT_SECRET" \ default_role="reader"