# Keyless connections

> Connect Google Vertex AI and Anthropic without storing any key: ACOG signs a short-lived identity token that your cloud account trusts.

Product: AI Cost Optimizer Gateway (ACOG). Web version: https://tessarac.com/docs/acog/providers/keyless-connections. Last updated: 2026-10-16.

A keyless connection stores **no credential at all**. Instead of handing ACOG a service-account key file or an API key, you tell your Google Cloud project or your Anthropic organization to trust an identity that ACOG issues for your organization. For every request, ACOG signs a short-lived token as that identity, exchanges it with Google or Anthropic for an access token, and uses that. There is nothing to rotate, nothing to leak, and access ends the moment you remove the trust on your side.

Keyless connections are available for:

| Provider | How you set it up | Page |
|---|---|---|
| Google Vertex AI (Gemini and Claude on Vertex) | A workload identity pool and OIDC provider in your Google Cloud project | [Google Vertex AI](https://tessarac.com/docs/acog/providers/google-vertex-ai.md) |
| Anthropic (direct API) | An issuer, a service account and a federation rule in the Claude Console | [Anthropic](https://tessarac.com/docs/acog/providers/anthropic.md) |

## How it works

1. **Your organization has its own identity.** ACOG runs an OpenID Connect issuer for each organization. Yours has an issuer URL and a subject, both shown in the console when you choose **Keyless** for a connection:

   | Value | Example |
   |---|---|
   | Issuer URL | `https://api.acog.tessarac.com/v1/identity/q4ztn6xo2bk7wmy3hfr5lc2pda` |
   | Subject | `acog:org:q4ztn6xo2bk7wmy3hfr5lc2pda` |

   Both are fixed for your organization and cannot be chosen. No other organization's tokens carry your issuer or your subject, so trusting them trusts your organization and nothing else.

2. **You configure your provider to trust that identity.** In Google Cloud that is a workload identity pool provider whose attribute condition admits only your subject. In Anthropic it is a federation rule that matches only your subject.

3. **ACOG exchanges a token on each use.** When the gateway needs to call your provider it asks ACOG's control plane to sign a token (valid for 30 minutes) for your organization, exchanges it at Google's Security Token Service or Anthropic's token endpoint, and caches the resulting access token until shortly before it expires.

4. **Your provider verifies the token** against your issuer's public keys at `<issuer URL>/.well-known/openid-configuration` and `<issuer URL>/jwks.json`. Google and Anthropic fetch these themselves; you do not upload anything.

The signing keys are held in AWS KMS on the hosted service and never leave it. ACOG rotates them automatically every 90 days, publishing each new key a day before it signs, so your provider already trusts it when it starts being used. You do not need to do anything when keys rotate.

## What a keyless connection stores

| Connection type | Stored settings | Stored secret |
|---|---|---|
| Google Vertex AI | Project, region, workload identity provider name, optional service account to impersonate | None |
| Anthropic | Organization ID, federation rule ID, service account ID, optional workspace ID | None |

When you switch an existing key-based connection to keyless, ACOG deletes its stored key. Switching back requires entering a key again.

## Self-hosted installations

On a self-hosted installation the same two options exist, plus a third: **install identity** (`ambient`), where the connection uses the identity your installation already runs as (for example GKE Workload Identity, a Google credentials file, or a projected Kubernetes service-account token trusted by Anthropic). See [Install identity for keyless connections](https://tessarac.com/docs/acog/self-hosted/install-identity.md).

A self-hosted installation offers keyless connections only when its operator has configured an issuer URL that Google and Anthropic can reach, or when the provider is given the key set directly. The console says so when keyless is not available.

## Troubleshooting

When an exchange is refused, the console shows the provider's short error code, and the gateway answers requests with `502 upstream_auth_error`. After a refusal the gateway waits 30 seconds before trying that connection again, so a misconfiguration costs one exchange every 30 seconds rather than one per request.

| What you see | Usual cause | Fix |
|---|---|---|
| `google refused the credentials (invalid_target)` | The workload identity provider name is wrong, or the provider or pool is disabled | Copy the provider's full resource name from Google Cloud and check it is enabled |
| `google refused the credentials (invalid_grant)` | The provider's issuer URL does not match your organization's, or its attribute condition does not match your subject | Compare the provider's issuer and condition with the values shown in the console |
| Google `403` on model calls after a successful exchange | The identity has no Vertex AI permission, or the model is not enabled for your project | Grant `roles/aiplatform.user` (shown in Google Cloud as **Agent Platform User**) and enable the model in Model Garden |
| `anthropic refused the credentials (authentication_error)` | The rule, service account or organization ID does not match, the issuer is not registered, or the rule's subject differs | Check the IDs, and the rule's issuer and subject, in the Claude Console. Its **Authentication events** list shows the reason |
| Model list falls back to "ACOG's current models" on Vertex | The identity may not list models (`serviceusage.services.use`) | Optional: grant `roles/serviceusage.serviceUsageConsumer`; requests work either way |
