This post documents a real-world example of enabling Google OIDC-based login for Vault.
It is based on an environment where Vault is managed via the official Helm chart using Terraform.
If you're looking to integrate a unified authentication mechanism across your organization using OIDC, this post may help.
For better understanding, check out this article first:
Why we introduced OIDC
Every employee in our organization is issued a Google Workspace account. As we adopted internal tools like Vault, ArgoCD, Grafana, and Jenkins, managing access control became increasingly important.
Creating and managing separate user accounts for each tool was both tedious and insecure. So we decided to unify authentication using Google OIDC, leveraging the accounts already in place.
This greatly reduced the complexity of user management and brought consistency to authentication across all systems.
Setup Process
Reference:
hashicorp/vault-guides - oidc-auth
1. Set up an OAuth client in Google Cloud Console
This process could potentially be replaced with the Terraform resource google_iam_oauth_client
in the future:
https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_oauth_client
I plan to refactor accordingly.
- Go to Google Cloud Console
- Select your project
- Navigate to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Choose Web application as the application type
- Select Web application as the Application type
- Set a name
- Add your Vault origin in Authorized JavaScript origins
-
Set the redirect URI as defined in the official documentation:
https://<your-vault-domain>/ui/vault/auth/oidc/oidc/callback
Once created, securely store the
client_id
andclient_secret
(e.g., Vault, AWS Secrets Manager)
2. Configure OIDC in Vault
// vault-config.tf
resource "vault_auth_backend" "oidc" {
type = "oidc"
path = "oidc"
}
resource "vault_generic_endpoint" "oidc_config" {
path = "auth/oidc/config"
data_json = jsonencode({
"oidc_discovery_url" = "https://accounts.google.com"
"oidc_client_id" = local.vault_secrets.vault_google_client_id
"oidc_client_secret" = local.vault_secrets.vault_google_client_secret
})
}
// vault-users.tf
resource "vault_generic_endpoint" "woobuntu" {
path = "auth/oidc/role/woobuntu"
data_json = jsonencode({
user_claim = "email"
oidc_scopes = "openid email"
bound_audiences = [local.vault_secrets.vault_google_client_id]
allowed_redirect_uris = ["https://vault.my-company.com/ui/vault/auth/oidc/oidc/callback"]
policies = [
// your Vault policies here
]
ttl = "1h"
bound_claims = {
"email" = "woobuntu@my-company.com"
}
})
}
We injected the client_id and client_secret issued in step 1. The remaining configuration follows the documentation below:
https://github.com/hashicorp/vault-guides/tree/master/identity/oidc-auth#configure-vault
https://developer.hashicorp.com/vault/api-docs/auth/jwt#create-update-role
💡 Note on role configuration
We chose to create a separate role per user because Vault does not currently support mapping multiple users to a single OIDC role via email matching. Initially, we tried assigning multiple emails via bound_claims, but bound_claims_type only supports string or glob—not arrays.
In the future, we plan to adopt group-based access control using the groups_claim and bound_claims.group features. This depends on broader adoption of Google Workspace groups within our organization.
💡 Security Tip
Avoid hardcoding sensitive credentials like client_id and client_secret in .tfvars or local variables. Instead, use a secure secret manager such as Vault or AWS Secrets Manager:
locals {
vault_secrets = jsondecode(data.aws_secretsmanager_secret_version.vault_secrets.secret_string)
}
Top comments (0)