Introduction
This guide provides step-by-step instructions on how to troubleshoot authentication issues when using the Google Cloud Platform (GCP) auth method with HashiCorp Vault. This assumes that you've already configured the GCP authentication method in Vault, set up the necessary GCP service account with required permissions, and generated a JWT token using the GCP Service Account Credentials API.
Problem Statement
While attempting to authenticate with Vault using the signed JWT token generated from the GCP Service Account Credentials API, you encounter the following error:
{"errors":["at least one of the JWT claim 'aud' must end in \"vault/$ROLE\""]}
About the aud Parameter
The aud (audience) claim is part of the JWT used to authenticate with Vault. This claim identifies the intended recipient of the JWT. When using the GCP auth method, the aud claim must match the Vault role associated with your authentication process.
Refer the implementation details for how Vault communicates with Google Cloud to authenticate and authorize JWT tokens.
Pre-requisites
Before proceeding, ensure that the following are set up:
- Set up the GCP authentication method in Vault by following the official Vault GCP Authentication Setup Guide.
- Verify that the GCP service account has the required permissions, as outlined in the Vault GCP Auth Method Permissions Guide.
- Ensure the necessary environment variables are set as specified in this section.
Example values for environment variables:
ROLE=vault-iam-xxxxxx-role
OAUTH_TOKEN=ya29.c.c0ASRK0GYsI7AUDt5vLWiy_……
SERVICE_ACCOUNT=hcpvault-sa@hc-xxxx.iam.gserviceaccount.com
EXPIRATION_TIME=173648..
JWT_CLAIM={\"aud\":\"vault/vault-iam-xxxxx-role\", \"sub\": \"hcpvault-sa@hc-xxxxxx.iam.gserviceaccount.com\", \"exp\": 173648...}
4. Generate the JWT token using the following API call:
curl \
--header "${OAUTH_TOKEN}" \
--header "Content-Type: application/json" \
--request POST \
--data "{\"payload\": \"${JWT_CLAIM}\"}" \
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${SERVICE_ACCOUNT}:signJwt"
Output Example:
{
"keyId": "2f60ae3d0ae92c986bf24af7611d0ff375cd5804",
"signedJwt": "eyJhbGciOiJSUzI1……..”
}
Cause of the Issue
Vault requires that the JWT token includes a specific claim set to authenticate successfully:
{
"sub": "$SERVICE_ACCOUNT_EMAIL_OR_ID",
"aud": "vault/$ROLE",
"exp": "$EXPIRATION_TIME"
}
Note : The exp claim should be in NumericDate format (seconds from the Epoch). Use EXPIRATION_TIME=$(date -v+15M +%s) to generate an expiration time.
Solution
Step 1: Decode the JWT Token
Use the JWT.io decoder to decode the JWT token you generated. Look for the payload section and check the value of the aud parameter.
For example, the decoded payload might look like:
Ensure that the aud value matches the expected format: vault/${ROLE}. In this case, it should look like:
{
"aud": "vault/vault-iam-xxxxxx-role",
"sub": "hcpvault-sa@hc-xxxxxxxxxx.iam.gserviceaccount.com",
"exp": 1736411944
}
Step 2: Correct the aud Claim
If the aud claim is incorrect (i.e., it does not match the Vault role configured), you need to update it to match the required format:
- Example: Change "aud": "vault-iam-xxxxxx-role" to "aud": "vault/vault-iam-xxxxxx-role"
Step 3: Authenticate with Vault
Once you've corrected the aud claim in the JWT token, you can proceed to authenticate with Vault using the following curl command:
response=$(curl -v \
--header "X-Vault-Token: ${VAULT_TOKEN}" \
--header "Content-Type: application/json" \
--request POST \
--data "{\"jwt\": \"${SIGNED_JWT}\", \"role\": \"${ROLE}\"}" \
"$VAULT_ADDR/v1/admin/auth/gcp/login")
Where:
- SIGNED_JWT is the JWT you received from the API.
- VAULT_TOKEN is an existing Vault token.
- VAULT_ADDR is the address of your Vault instance (e.g., http://127.0.0.1:8200).
Step 4: Fetch the Client Token
Once the request is successful, you'll receive a response containing the Vault client token:
{
"request_id": "931a9528-7054-27ec-1124-1a5472082820",
"auth": {
"client_token":"hvs.CAESIGpCVdL7S8Nh2U3xylW-bnh5MKCbRIRFikw0UM5VggK0GikQUVZkZWF1..........",
policies": ["default", "dev"],
"lease_duration": 3600
}
}
To extract the client token, use the following command:
echo "$response" | jq -r '.auth.client_token'
Output:
hvs.CAESIGpCVdL7S8Nh2U3xylW-bnh5MKCbRIRFikw0UM5VggK0GikKImh2cy5GajVwMkZQUVZkZWF1........
Now, you have a valid client token that you can use for subsequent requests to Vault, such as reading secrets, writing data, etc.
Conclusion
By correcting, the aud claim in your JWT token to match the Vault role format (vault/${ROLE}), you should be able to authenticate successfully using the GCP auth method. Always ensure the JWT payload is correctly formed according to Vault's expectations before attempting authentication.