AppRole authentication is Vault’s way of letting machines, not humans, get secrets.

Let’s see it in action. Imagine a web server that needs a database password. Instead of embedding that password (bad!), it uses AppRole to get a temporary token from Vault.

# On the web server, we have two pieces of information:
# 1. The Role ID (publicly known)
# 2. The Secret ID (secret, like a password)

# First, we authenticate with AppRole to get a Vault token
curl \
    --request POST \
    --data '{"role_id": "your-role-id", "secret_id": "your-secret-id"}' \
    http://127.0.0.1:8200/v1/auth/approle/login

# If successful, Vault returns a token:
# {
#   "request_id": "...",
#   "lease_id": "",
#   "renewable": false,
#   "lease_duration": 0,
#   "data": {
#     "client_token": "s.your-vault-token",
#     "accessor": "...",
#     "policies": ["webserver-policy"],
#     "token_policies": ["webserver-policy"],
#     "metadata": {
#       "role": "webserver-role",
#       "username": "your-role-id"
#     },
#     "lease_duration": 2592000,
#     "renewable": true,
#     "entity_id": "...",
#     "token_type": "service",
#     "orphan": false
#   },
#   "wrap_info": null,
#   "warnings": null
# }

# Now, use this token to read the database secret
curl \
    --header "X-Vault-Token: s.your-vault-token" \
    http://127.0.0.1:8200/v1/secret/data/database/config

# Vault returns the secret:
# {
#   "request_id": "...",
#   "lease_id": "",
#   "renewable": false,
#   "lease_duration": 0,
#   "data": {
#     "data": {
#       "username": "dbuser",
#       "password": "dbpassword123"
#     },
#     "metadata": {
#       "created_time": "2023-10-27T10:00:00.000000000Z",
#       "deletion_time": "0001-01-01T00:00:00Z",
#       "destroyed": false,
#       "version": 1
#     }
#   },
#   "wrap_info": null,
#   "warnings": null
# }

The core problem AppRole solves is providing a secure, automated way for applications to authenticate with Vault without relying on long-lived credentials or complex human-driven workflows. It decouples the identity of the machine (represented by the Role ID) from its credentials (the Secret ID), which can be managed and rotated independently.

Internally, AppRole works by defining "roles" within Vault. Each role has a role_id and can be configured with one or more secret_ids. When an application wants to authenticate, it presents its role_id and one of its associated secret_ids to the /auth/approle/login endpoint. Vault validates this combination against the defined role. If successful, Vault issues a short-lived, signed token back to the application. This token is tied to the specific AppRole that authenticated it and has policies attached to it, granting it precisely the permissions needed to access secrets. The secret_id itself is single-use and can be configured to expire, adding a layer of security.

The power of AppRole lies in its flexibility. You can configure it to use different Secret ID types: a single, static Secret ID; a Secret ID that is generated by Vault and can be bound to a specific period or number of uses; or even a Secret ID bound to a specific piece of hardware. This allows you to tailor the security model to your environment, from simple setups to highly secure, ephemeral credential rotations. The role_id is public, meaning you can bake it into your application’s configuration or even its container image. The secret_id, however, must be treated with the utmost care, often injected into the application environment at runtime through other secure means, like Kubernetes Secrets or an initial bootstrap process.

One critical aspect that trips people up is the difference between role_id and secret_id lifecycle. The role_id is essentially a public identifier for a type of application or service. It’s not secret, and it doesn’t change unless you fundamentally alter the role’s definition. The secret_id, on the other hand, is the actual credential for authentication. Vault’s AppRole backend can be configured to generate these secret_ids automatically. When you create an AppRole and tell Vault to generate secret_ids, Vault will give you a secret_id and a secret_id_accessor. You need to store that secret_id securely because it’s what your application uses to log in. The secret_id_accessor can be used to manage the secret_id (e.g., to revoke it), but it’s not used for the actual login. This distinction is crucial for managing credential rotation and revocation effectively.

The next hurdle is handling token renewal and revocation, especially when your application needs to maintain access for longer than the initial token lease duration.

Want structured learning?

Take the full Vault course →