Workload identity: Google Cloud

⚠️
Preview — this feature is being built; the design below is the spec.

Workloads on Google Cloud (Cloud Run, Cloud Functions, GKE with Workload Identity, Compute Engine) run as a Google service account and can fetch a signed identity token for any audience from the metadata server. Exchange that token for a Syntic access token and no Syntic secret needs to live in Secret Manager or environment variables.

Claims you can match on

ClaimExampleUse it to
emailsummariser@acme-prod.iam.gserviceaccount.comTrust one Google service account.
sub112233445566778899000The service account’s unique numeric id; does not change if the account is renamed.
email_verifiedtrueRequired to be true for email to be meaningful.

Matching on sub is the most robust choice; email is easier to read. Using both is fine.

Set it up

Note the Google service account

Find the service account your workload runs as, and its unique id:

gcloud iam service-accounts describe summariser@acme-prod.iam.gserviceaccount.com --format='value(uniqueId)'

Create the Syntic service account and trust rule

{
  "issuer": "https://accounts.google.com",
  "audience": "https://app.syntic.ai",
  "conditions": {
    "sub": "112233445566778899000",
    "email": "summariser@acme-prod.iam.gserviceaccount.com",
    "email_verified": "true"
  },
  "max_token_lifetime_seconds": 1800
}

Fetch and exchange the token in your code

# pip install google-auth requests
import requests
import google.auth.transport.requests
from google.oauth2 import id_token
 
jwt = id_token.fetch_id_token(google.auth.transport.requests.Request(), "https://app.syntic.ai")
tok = requests.post(
    "https://app.syntic.ai/v1/oauth/token",
    headers={"syntic-beta": "token-exchange-2026-11-01"},
    json={
        "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
        "subject_token": jwt,
        "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
        "service_account": "svcacct_01JCB3D5F7H9K1M3P5R7",
    },
    timeout=30,
).json()
syntic_token = tok["access_token"]          # valid for tok["expires_in"] seconds

Refresh before expiry

Cache the Syntic token and exchange a new Google token a minute or two before expires_in runs out. Google identity tokens themselves last about an hour, and the libraries above refresh them for you.

Each Google service account should map to its own Syntic service account. Sharing one Syntic service account between several Google identities makes the audit log less useful.

Was this page helpful?