Agents hosted on Google Cloud can use their own identity to authenticate to tools and services hosted on Google Cloud runtimes, such as Cloud Run or Google Kubernetes Engine (GKE), by requesting an OpenID Connect (OIDC) ID token from Agent Identity. Agents can also use these ID tokens to authenticate to third-party cloud platforms (such as Amazon Web Services (AWS) and Microsoft Azure), custom APIs, API gateways, and on-premises backends.
When an agent acts on its own authority to access an external service, Agent Identity issues an OpenID Connect (OIDC) ID token. This JSON Web Token (JWT) asserts the agent's SPIFFE identity and is signed by the issuer keys for the agent's trust domain (managed workload identity pool). External systems can verify these tokens without Google Cloud credentials or SDKs through public endpoints hosted by the Google Cloud Security Token Service:
- An OpenID Connect Discovery 1.0 endpoint
(
/.well-known/openid-configuration) that publishes the OpenID provider metadata and the public key endpoint (jwks_uri). - A JSON Web Key Set (JWKS) endpoint (
/openid/jwks) that serves the active public keys used to verify signatures on agent ID tokens.
Before you begin
- Verify that you have chosen the correct authentication method. Review how SPIFFE identities, trust domains, and agent credentials work in the Agent Identity overview.
- Create and deploy an agent with Agent Identity enabled.
- Ensure that your external service or identity provider meets the following
requirements:
- Supports validating JSON Web Tokens (JWTs) using OpenID Connect Discovery 1.0 and JSON Web Key Sets (JWKS).
- Can send outbound HTTPS requests to
https://sts.googleapis.comto retrieve the OpenID Provider metadata and public signing keys.
- Identify the following configuration values for your agent and target
external service:
- Issuer URL (
issclaim): The workload identity pool issuer URL for your organization (https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/TRUST_DOMAIN) or project (https://sts.googleapis.com/v1/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/TRUST_DOMAIN). - Allowed audience (
audclaim): The audience URI that the external service or identity provider expects when validating ID tokens.
- Issuer URL (
- Verify that you have the roles required to complete this task.
Required roles
To get the permissions that you need to deploy an agent with Agent Identity, ask your administrator to grant you the following IAM roles on your project:
-
Deploy an agent to Agent Runtime on Gemini Enterprise Agent Platform:
Vertex AI User (
roles/aiplatform.user) -
Deploy an agent service to Cloud Run:
Cloud Run Admin (
roles/run.admin)
For more information about granting roles, see Manage access to projects, folders, and organizations.
These predefined roles contain the permissions required to deploy an agent with Agent Identity. To see the exact permissions that are required, expand the Required permissions section:
Required permissions
The following permissions are required to deploy an agent with Agent Identity:
-
Deploy an agent to Agent Runtime on Gemini Enterprise Agent Platform:
-
aiplatform.reasoningEngines.create -
aiplatform.reasoningEngines.update
-
-
Deploy an agent service to Cloud Run:
-
run.services.create -
run.services.update
-
You might also be able to get these permissions with custom roles or other predefined roles.
Obtain an OIDC ID token for an agent
To configure your agent to obtain and send an OIDC ID token to an external service, complete the following tasks:
Configure your agent with Agent Identity
Enable Agent Identity when you deploy your agent:
If you deploy your agent to Agent Runtime on Gemini Enterprise Agent Platform , set
identity_typetoAGENT_IDENTITY:remote_app = client.agent_engines.create( agent=app, config={ "identity_type": types.IdentityType.AGENT_IDENTITY, "requirements": ["google-cloud-aiplatform[agent_engines,adk]"], }, )If you deploy a containerized agent service to Cloud Run, pass the
--identity-type=agent-identityflag:gcloud run deploy SERVICE_NAME \ --image=IMAGE_URL \ --identity-type=agent-identity \ --no-allow-unauthenticated
Replace the following:
SERVICE_NAME: The name of your Cloud Run service.IMAGE_URL: The container image URL for your agent.
Request an OIDC ID token in application code
In your agent's application code, use the Google Auth client library to request an OIDC ID token for your target external audience. The client library handles token generation, local caching, and automatic renewal from the metadata server.
By default, OIDC ID tokens issued for external audiences aren't bound to the runtime certificate.
The following example uses the google-auth library to request an OIDC ID
token and attach it as a Bearer token in an outgoing request:
Python
from google.auth.transport.requests import AuthorizedSession from google.oauth2 import id_token # 1. Specify the audience expected by the external receiver # (for example, AWS Bedrock AgentCore or your external service URL). target_audience = "https://EXTERNAL_SERVICE_AUDIENCE" # 2. Create ID token credentials and an AuthorizedSession, which handles # local token caching, automatic renewal before expiry, and the Bearer header. credentials = id_token.fetch_id_token_credentials(audience=target_audience) authed_session = AuthorizedSession(credentials) # 3. Send the authenticated request to the external service. response = authed_session.post( "https://EXTERNAL_SERVICE_ENDPOINT", json={"prompt": "Hello from Agent"}, )
Replace the following:
EXTERNAL_SERVICE_AUDIENCE: The audience URI expected by your receiving service (for example,bedrock.us-east-1.amazonaws.comorapi.example.com).EXTERNAL_SERVICE_ENDPOINT: The URL of the external API or backend endpoint that your agent calls.
For client library instructions and examples in other programming languages
(including Go, Node.js, and Java), see
Get an ID token. Current client library
versions for these languages support --identity-type=agent-identity, but
don't use bound tokens by default.
Verify Agent Identity ID tokens
When an external service receives an OIDC ID token from your agent, verify the token using either of the following approaches based on the target service:
- Managed cloud platforms (such as Cloud Run, AWS, or Microsoft Azure): Use built-in workload identity federation to verify incoming tokens without writing custom verification code.
- Custom backend services, API gateways, and on-premises workloads: Verify tokens programmatically using the public OpenID Connect Discovery and JWKS endpoints.
Use built-in workload identity federation
If your receiving service runs on a cloud platform that supports built-in IAM authentication or OIDC workload identity federation, you don't need to write custom token verification code:
Cloud Run: If your receiving service runs on Cloud Run with authenticated ingress (
--no-allow-unauthenticated), Cloud Run validates incoming Agent Identity tokens at the ingress layer. Grant the calling agent the Cloud Run Invoker (roles/run.invoker) role on the receiving service. For more information, see Authenticate to MCP servers on Cloud Run.If your service allows unauthenticated ingress and verifies tokens in application code, see Verify tokens programmatically.
Amazon Bedrock: Configure inbound JWT authentication by specifying the Google Cloud Security Token Service discovery URL or issuer URL and your expected audience. For instructions, see Configure inbound JWT authorizer in the AWS documentation.
Microsoft Entra ID: Configure a federated identity credential with the Other issuer scenario. Specify the Google Cloud Security Token Service issuer URL, the expected audience, and the subject identifier (
subclaim). For instructions, see Create a trust relationship between an app and an external identity provider in the Microsoft Learn documentation.
Verify tokens programmatically
If your agent sends requests to a custom API, microservice, API gateway, or
on-premises workload, your receiving service must verify the incoming OIDC ID
token before granting access. Your agent typically passes this token in the
Authorization: Bearer TOKEN HTTP header.
To verify incoming ID tokens programmatically, complete the following tasks:
- Extract and validate the token issuer URL
- Discover and cache the public signing keys
- Verify the token signature and claims
- Authorize the agent's SPIFFE identity
Extract and validate the token issuer URL
When an incoming request arrives, read the unverified JWT payload to extract the
iss (issuer) claim. This claim contains the URL of the workload identity pool
for the agent's
trust domain. This URL
serves as the base URL for the discovery document and public signing keys.
Before making any outgoing network requests, verify that the iss claim matches
the expected Google Cloud Security Token Service workload identity pool URL for your
organization or project:
Organization-level trust domains:
https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/TRUST_DOMAIN
For example, for an organization with ID
123456789012,TRUST_DOMAINisagents.global.org-123456789012.system.id.goog.Project-level trust domains (for projects without an organization):
https://sts.googleapis.com/v1/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/TRUST_DOMAIN
For example, for a project with number
9876543210,TRUST_DOMAINisagents.global.proj-9876543210.system.id.goog.
Discover and cache the public signing keys
After you validate the issuer URL, retrieve and cache the public signing keys from the Google Cloud Security Token Service:
-
Query the OpenID Connect Discovery endpoint: Append
/.well-known/openid-configurationto the base issuer URL and send an unauthenticated HTTPGETrequest:Before using any of the request data, make the following replacements:
ORGANIZATION_ID: Your Google Cloud organization ID. For a project without an organization, replaceorganizations/ORGANIZATION_IDwithprojects/PROJECT_NUMBER.TRUST_DOMAIN: The workload identity pool ID for your agent's trust domain (for example,agents.global.org-123456789012.system.id.goog).
HTTP method and URL:
GET https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/TRUST_DOMAIN/.well-known/openid-configuration
To send your request, expand one of these options:
A successful request returns an
HTTP 200 OKstatus and a JSON object containing the OpenID Provider metadata, including thejwks_urifield:{ "issuer": "https://sts.googleapis.com/v1/organizations/123456789012/locations/global/workloadIdentityPools/agents.global.org-123456789012.system.id.goog", "jwks_uri": "https://sts.googleapis.com/v1/organizations/123456789012/locations/global/workloadIdentityPools/agents.global.org-123456789012.system.id.goog/openid/jwks", "authorization_endpoint": "https://sts.googleapis.com/v1/organizations/123456789012/locations/global/workloadIdentityPools/agents.global.org-123456789012.system.id.goog/authorize", "token_endpoint": "https://sts.googleapis.com/v1/organizations/123456789012/locations/global/workloadIdentityPools/agents.global.org-123456789012.system.id.goog/token", "response_types_supported": [ "id_token" ], "subject_types_supported": [ "public" ], "id_token_signing_alg_values_supported": [ "RS256" ] } -
Query the JSON Web Key Set (JWKS) endpoint: Send an unauthenticated HTTP
GETrequest to thejwks_uriURL returned in the OpenID Provider metadata:Before using any of the request data, make the following replacements:
ORGANIZATION_ID: Your Google Cloud organization ID. For a project without an organization, replaceorganizations/ORGANIZATION_IDwithprojects/PROJECT_NUMBER.TRUST_DOMAIN: The workload identity pool ID for your agent's trust domain (for example,agents.global.org-123456789012.system.id.goog).
HTTP method and URL:
GET https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/TRUST_DOMAIN/openid/jwks
To send your request, expand one of these options:
A successful request returns an
HTTP 200 OKstatus and a JSON object containing an array of public keys formatted according to RFC 7517:{ "keys": [ { "kty": "RSA", "use": "sig", "alg": "RS256", "kid": "4d1933f8e6c4e0b512c140989f6655c68997...", "n": "uQn4zN_1mQ0VpGv82-Wp3w...", "e": "AQAB" } ] } -
Cache the discovery document and keys: Responses from both the OpenID Connect Discovery endpoint and the JWKS endpoint include the following HTTP cache header:
Cache-Control: public, max-age=86400, must-revalidate
Cache the discovery document and JWKS for up to 24 hours (
86400seconds) to improve verification performance and avoid rate limiting.Google Cloud periodically rotates the private and public signing keys for workload identity pools. If your verifier receives an incoming token with a
kid(key ID) that isn't in its local key cache, fetch a fresh JWKS from the/openid/jwksendpoint before rejecting the token.If you encounter HTTP errors when querying the discovery or JWKS endpoints, see Troubleshoot Agent Identity authentication issues.
Verify the token signature and claims
To cryptographically verify the token signature and validate the JWT claims, use a standard OIDC or JWT verification library (such as Google Tink) and do the following:
- Signature: Find the public key in the cached JWKS that matches the
kid(key ID) in the JWT header. Validate the signature using the algorithm specified in thealgfield (RS256). For forward compatibility, inspect thealgandktyfields in the JWKS dynamically rather than hardcoding algorithm types. - Issuer (
iss): Confirm that theissclaim matches the trusted Google Cloud workload identity pool issuer URL for your trust domain. - Audience (
aud): Confirm that theaudclaim matches your service's configured audience identifier. - Issued-at time (
iat) and expiration time (exp): Verify that theiatclaim is in the past and that the current time is earlier than theexpclaim (allowing a small clock-skew tolerance, such as 1 to 2 minutes).
The following example uses Google Tink (tink.jwt) to verify an Agent Identity
ID token against a JWKS JSON payload:
Python
import tink from tink import jwt # Initialize Tink JWT signature primitives (call once at application startup). jwt.register_jwt_signature() def verify_agent_identity_token( token: str, jwks_json: str, expected_issuer: str, expected_audience: str, ) -> jwt.VerifiedJwt: """Verifies an Agent Identity JWT against a JWKS JSON string using Tink. Args: token: The compact serialized JWT string. jwks_json: The JWKS JSON string fetched from the STS pool endpoint. expected_issuer: The expected token issuer ('iss' claim). expected_audience: The expected token audience ('aud' claim). Returns: jwt.VerifiedJwt: The verified JWT claims object. Raises: tink.TinkError: If the JWKS cannot be parsed, the key is not found, or token validation (signature, issuer, audience, expiration) fails. """ # 1. Convert the JWKS JSON into a Tink public KeysetHandle. keyset_handle = jwt.jwk_set_to_public_keyset_handle(jwks_json) # 2. Instantiate the Tink JwtPublicKeyVerify primitive. jwt_verifier = keyset_handle.primitive(jwt.JwtPublicKeyVerify) # 3. Configure expected validation rules (issuer, audience, expiration). # Google Cloud STS sets 'typ': 'JWT' in the header, so # expected_type_header="JWT" is required. validator = jwt.new_validator( expected_issuer=expected_issuer, expected_audience=expected_audience, expected_type_header="JWT", allow_missing_expiration=False, ) # 4. Cryptographically verify the signature and standard OIDC claims. return jwt_verifier.verify_and_decode(token, validator)
Authorize the agent's SPIFFE identity
After you verify the token's signature and standard claims, inspect the verified
sub (subject) claim to authorize the request and record the calling agent in
your audit logs.
The sub claim contains the agent's unique
SPIFFE ID, for example:
spiffe://agents.global.org-123456789012.system.id.goog/resources/aiplatform/projects/9876543210/locations/us-central1/reasoningEngines/my-test-agent
In your service's authorization logic, compare the verified sub claim against
an allowlist of trusted agent SPIFFE IDs (or trust domain prefixes) before
granting access to protected resources.
What's next
- Troubleshoot Agent Identity authentication issues
- Authenticate to Google Cloud using an agent's own identity
- Authenticate using 2-legged OAuth with auth manager
- Authenticate using 3-legged OAuth with auth manager
- Authenticate using API key with auth manager
- Agent Identity overview