Skip to main content

Configure JWT authentication

Learn how to create a JWT access token, set up Vault to authenticate it, and use the token to access the REST API

You can use a JWT access token generated by an external identity provider to request a Vault IAM role that enables a call to the Vault REST API. The JWT can be defined to restrict access further than the role, and you can configure Vault to validate a token based on additional access restrictions.

In this guide, you create an access token that requests the use of a role and define the IAM configuration file settings to validate that token.

warning

For security reasons, don't use your JWTs for other applications with Vault; issue JWTs dedicated to communication with Vault.

JWT authentication basics

When you call the REST API, you provide a JWT access token in the call's Authorization header in the same manner as done for a Bearer token. When Vault receives the call, it validates the JWT access token to confirm that:

  • It has not expired.
  • The token's iss and aud key values match those in an idps table in the IAM configuration file.
  • The roles claim contains only one role, and that role is in the IAM configuration.
  • It's signed using the public key defined in the IAM configuration.
  • It's claims are valid and match any settings in the IAM configuration file.

If the token is valid, Vault uses the roles claim in the token to set the user's role.

Overview

The steps you take to create the JWT access token and set up Vault to validate it are:

  • Create public and private keys to sign the token and prepare the keys for use in a JWT token.
  • Create the JWT token using jwt.io. For production, you must use an identity provider such as Auth0, Azure AD, etc.
  • Add an idps table to the IAM configuration file.
  • Call the REST API using your JWT token as the bearer token.

Step-by-step

note

In practice, you create the JWT token through your chosen identity provider and receive a JWKS endpoint link for the public key.

Create a signing key-pair

Generate a public and private key using these commands:

openssl genrsa -out pvault_jwt_private_key.pem 2048
openssl rsa -pubout -in pvault_jwt_private_key.pem -out pvault_jwt_public_key.pem

Now open the pvault_jwt_private_key.pem and pvault_jwt_public_key.pem file to obtain the keys, for example:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt3wbPZPZFAKln1dzrEd6
sg3FFG0/lqkvFgKaEQB8ZMPnFJm16CMY8C4zjO4TVktsY6klqzFL2mEldLiKJ1Ze
kiAy0eZgW8Icm6tRkMiYkSTRAcCqxNxKQOS6Yr8q6FMkAcnxWIoJyAwdXj9BWzet
CKBfW+vQ3z6CXs0e+ty5JMN7UqxwWPBBeEYxgNrZggR5tyKB3TFMXZFvBAbNM7vx
fEy7ObxL60IYMguTKNLJJyYx6AZsDXHt+iW72pmoUhhm/rCuFo4aKqJvGqoYkOST
Vigm8OfjD921fWp1v8Remq9hf9hS19VsP4yRL8ogFRnhoGy32FcOugnoo23jaXVG
5QIDAQAB
-----END PUBLIC KEY-----

Turn the public key into JWT format using JWK Creator with these settings:

  • Public Key Use: Signing
  • Algorithm: RS256
  • Key ID: abc
  • PEM encoded key: the public key you generated.

Click Convert, and you're returned the key in JWI format, for example:

{
"kty": "RSA",
"n": "t3wbPZPZFAKln1dzrEd6sg3FFG0_lqkvFgKaEQB8ZMPnFJm16CMY8C4zjO4TVktsY6klqzFL2mEldLiKJ1ZekiAy0eZgW8Icm6tRkMiYkSTRAcCqxNxKQOS6Yr8q6FMkAcnxWIoJyAwdXj9BWzetCKBfW-vQ3z6CXs0e-ty5JMN7UqxwWPBBeEYxgNrZggR5tyKB3TFMXZFvBAbNM7vxfEy7ObxL60IYMguTKNLJJyYx6AZsDXHt-iW72pmoUhhm_rCuFo4aKqJvGqoYkOSTVigm8OfjD921fWp1v8Remq9hf9hS19VsP4yRL8ogFRnhoGy32FcOugnoo23jaXVG5Q",
"e": "AQAB",
"alg": "RS256",
"kid": "abc",
"use": "sig"
}
tip

If you don't get the same key-value pairs, refresh the page and try again.

info

Vault supports using a JWKS endpoint to fetch a public key by setting "jwks_uri" in the IAM configuration. Identity providers, such as Auth0, provide a URL to a JWKS endpoint that contains the public key in JWT format.

Update the IAM configuration file

First, define the content of the idps table. This includes:

  • The issuer (iss) is an identifier for the site used to create the token or the third-party provider that needs to match the information provided in the token. In this case, use the URL of the site you use to generate the token, i.e., https://jwt.io/.
  • The audience (aud) is an arbitrary value to match with the IAM file configuration: use a meaningful value. For this example, use vault1.
  • The key (key) is the JSON you got from JWK Creator when you encoded the public key.
  • An identifier for the tables for this identity provider. This identifier can appear in Vault logs. In this case, use app1.
note

If the IdP uses a role claim name other than "roles" set roles_claim to identify the role claim.

This results in an idps table like this:

[idps]

[idps.app1]
type = "direct-jwt"

[idps.app1.conf]
iss = "https://jwt.io/"
aud = "vault1"
keys = "{\"kty\":\"RSA\",\"n\":\"t3wbPZPZFAKln1dzrEd6sg3FFG0_lqkvFgKaEQB8ZMPnFJm16CMY8C4zjO4TVktsY6klqzFL2mEldLiKJ1ZekiAy0eZgW8Icm6tRkMiYkSTRAcCqxNxKQOS6Yr8q6FMkAcnxWIoJyAwdXj9BWzetCKBfW-vQ3z6CXs0e-ty5JMN7UqxwWPBBeEYxgNrZggR5tyKB3TFMXZFvBAbNM7vxfEy7ObxL60IYMguTKNLJJyYx6AZsDXHt-iW72pmoUhhm_rCuFo4aKqJvGqoYkOSTVigm8OfjD921fWp1v8Remq9hf9hS19VsP4yRL8ogFRnhoGy32FcOugnoo23jaXVG5Q\",\"e\":\"AQAB\",\"alg\":\"RS256\",\"kid\":\"abc\",\"use\":\"sig\"}"

Add this content to the IAM toml file following the instructions in Update the IAM configuration. Note that there may be a default empty [idps] table in your toml file.

Generate a JWT access token

To generate the access token, use jwt.io.

First, create the header content. Here you set the:

  • Algorithm ("alg") used to encode the token to "RS256".
  • Type ("typ") to "JWT".
  • Key ID ("kid") to the one you set when converting your public key, i.e., "abc".

Which results in this JSON that you add to the HEADER section:

{
"alg": "RS256",
"typ": "JWT",
"kid": "abc"
}

Next, create the payload where the:

  • Issuer ("iss") is https://jwt.io/.
  • Audience ("aud") is vault1.
  • Subject ("sub") is the user claiming the role. For this example, use the "VaultAdmin" user, but you could use an email or any other helpful identifier.
  • Token's expiration date ("exp") is a time in the future.
  • Claimed role ("roles") must be present in the IAM configuration. For this example, use the "VaultAdmin" role.

Which results in this JSON that you add to the PAYLOAD section:

{
"iss": "https://jwt.io/",
"aud": "vault1",
"sub": "VaultAdmin",
"exp": 1893412799,
"roles": ["VaultAdminRole"]
}

Finally, add the public and private keys you generated earlier to the VERIFY SIGNATURE section.

Now, generate the encoded token. You get a result similar to this:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFiYyJ9.eyJpc3MiOiJodHRwczovL2p3dC5pby8iLCJhdWQiOiJ2YXVsdDEiLCJzdWIiOiJWYXVsdEFkbWluIiwiZXhwIjoxODkzNDEyNzk5LCJyb2xlcyI6WyJWYXVsdEFkbWluUm9sZSJdfQ.CXTyS-j9rVyJw0VOkysQDUmRiF4GW1jNqPBxD2cRhcG9RwJRFnMx_U0l6h9C--dESGHhf8yeOIgkB_24FpuyyWzc8rPpewa2DzfPJS-iqQD9JjKIParSpp79p6ZfFLwRdHEvME8Xbdj_YVP2IchrEhuk3LwgFIfS1Scq7z9aEsB3h_fARI81hPugzODYkl77vo3D0hb0W9SmZprKuVtCY8NA2-qDK6HWZNXSjVkWJgzLttlzjwfU6WhKCR0cYHgmiE9Mt_tBeHF_m03Y8BqhF2yDQKpOo6ptohUZLYynarhBlApGrOkbs9zQdwKmQwaVlQxRQhnEjcxsIu7HwkYmxg

Test the JWT access token

Use the JWT access token to authenticate to Vault. For example, to get the version of Vault, you use pvault --authtoken <jwt> version, which would look something like this:

pvault --authtoken eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFiYyJ9.eyJpc3MiOiJodHRwczovL2p3dC5pby8iLCJhdWQiOiJ2YXVsdDEiLCJzdWIiOiJWYXVsdEFkbWluIiwiZXhwIjoxODkzNDEyNzk5LCJyb2xlcyI6WyJWYXVsdEFkbWluUm9sZSJdfQ.CXTyS-j9rVyJw0VOkysQDUmRiF4GW1jNqPBxD2cRhcG9RwJRFnMx_U0l6h9C--dESGHhf8yeOIgkB_24FpuyyWzc8rPpewa2DzfPJS-iqQD9JjKIParSpp79p6ZfFLwRdHEvME8Xbdj_YVP2IchrEhuk3LwgFIfS1Scq7z9aEsB3h_fARI81hPugzODYkl77vo3D0hb0W9SmZprKuVtCY8NA2-qDK6HWZNXSjVkWJgzLttlzjwfU6WhKCR0cYHgmiE9Mt_tBeHF_m03Y8BqhF2yDQKpOo6ptohUZLYynarhBlApGrOkbs9zQdwKmQwaVlQxRQhnEjcxsIu7HwkYmxg version

You get a response like this:

+--------------------+-----------------------------+----------------------+-------------------+ | vault_id | vault_version | cli_version | db_schema_version | +--------------------+-----------------------------+----------------------+-------------------+ | 384662711408558080 | 1.14.0.12018547267-g52945f2 | v1.14.0-0-g52945f25a | 20241125194329 | +--------------------+-----------------------------+----------------------+-------------------+

What next