Follow Discord
Sweep 22 Oct 2026 · 21:04Z Build v2.1.309 528 read Stable v2.1.308 Latest v2.1.309 Next v2.1.309 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · api

gcp changedmanage-claude/wif-providers/gcp

Nearest release: v2.1.309, published 3 hours before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Recorded here
Lines+82added
Lines−82removed
From line 162 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits14to this page, all time

The whole hunk

from line 162, old and new numbered
/
lines
from line 162
162162 }'
163163 ```
164164 
165 ```bash CLI
166 # Write the Google-signed identity token to a file the CLI can read
167 export ANTHROPIC_IDENTITY_TOKEN_FILE=$(mktemp)
168 curl -sS -H "Metadata-Flavor: Google" \
169 "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://api.anthropic.com&format=full" \
170 > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
171 
172 # ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID,
173 # ANTHROPIC_SERVICE_ACCOUNT_ID, and ANTHROPIC_WORKSPACE_ID are read from the environment.
174 ant messages create \
175 --model claude-opus-5-5 \
176 --max-tokens 1024 \
177 --message '{role: user, content: "Hello from Cloud Run"}'
178 ```
179 
165180 ```python Python
166181 import os
167182 import anthropic
from line 248
233248 }
234249 ```
235250 
251 ```csharp C#
252 using Anthropic.Credentials;
253 // ...
254 
255 var credentials = new WorkloadIdentityCredentials(new WorkloadIdentityOptions
256 {
257 FederationRuleId = Environment.GetEnvironmentVariable("ANTHROPIC_FEDERATION_RULE_ID")!,
258 OrganizationId = Environment.GetEnvironmentVariable("ANTHROPIC_ORGANIZATION_ID"),
259 ServiceAccountId = Environment.GetEnvironmentVariable("ANTHROPIC_SERVICE_ACCOUNT_ID"),
260 WorkspaceId = Environment.GetEnvironmentVariable("ANTHROPIC_WORKSPACE_ID"),
261 IdentityTokenProvider = new MetadataTokenProvider(),
262 });
263 using var client = new AnthropicClient(new ClientOptions { Credentials = credentials });
264 
265 var message = await client.Messages.Create(new()
266 {
267 Model = Model.ClaudeOpus5_5,
268 MaxTokens = 1024,
269 Messages = [new UserMessageParam { Content = "Hello from Cloud Run" }],
270 });
271 foreach (var block in message.Content)
272 {
273 if (block.Value is TextBlock textBlock)
274 {
275 Console.WriteLine(textBlock.Text);
276 }
277 }
278 
279 class MetadataTokenProvider : IIdentityTokenProvider
280 {
281 private const string METADATA_URL =
282 "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://api.anthropic.com&format=full";
283 
284 private static readonly HttpClient httpClient = new()
285 {
286 DefaultRequestHeaders = { { "Metadata-Flavor", "Google" } },
287 };
288 
289 public async Task<string> GetIdentityTokenAsync(CancellationToken ct = default)
290 {
291 return await httpClient.GetStringAsync(METADATA_URL, ct);
292 }
293 }
294 ```
295 
236296 ```go Go
237297 const audience = "https://api.anthropic.com"
238298 
from line 350
290350 void main() throws Exception {
291351 HttpClient http = HttpClient.newHttpClient();
292352 HttpRequest metadataRequest = HttpRequest.newBuilder()
293 .uri(URI.create("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://api.anthropic.com&format=full"))
294 .header("Metadata-Flavor", "Google")
295 .build();
353 .uri(URI.create("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://api.anthropic.com&format=full"))
354 .header("Metadata-Flavor", "Google")
355 .build();
296356 
297357 // The Java SDK takes the token itself or a file path, not a function; with
298358 // source("value"), path(...) holds the token. The SDK sends that same token
from line 363
303363 String googleIdentityToken = http.send(metadataRequest, HttpResponse.BodyHandlers.ofString()).body();
304364 
305365 AnthropicClient client = AnthropicOkHttpClient.builder()
306 .configurationProvider(InMemoryProfileConfigProvider.of(ProfileConfig.builder()
307 .organizationId(System.getenv("ANTHROPIC_ORGANIZATION_ID"))
308 .workspaceId(System.getenv("ANTHROPIC_WORKSPACE_ID"))
309 .authentication(AuthenticationConfig.builder()
310 .type(AuthenticationType.OIDC_FEDERATION)
311 .federationRuleId(System.getenv("ANTHROPIC_FEDERATION_RULE_ID"))
312 .serviceAccountId(System.getenv("ANTHROPIC_SERVICE_ACCOUNT_ID"))
313 .identityToken(IdentityTokenConfig.builder()
314 .source("value")
315 .path(googleIdentityToken)
316 .build())
317 .build())
318 .build()))
319 .build();
366 .configurationProvider(InMemoryProfileConfigProvider.of(ProfileConfig.builder()
367 .organizationId(System.getenv("ANTHROPIC_ORGANIZATION_ID"))
368 .workspaceId(System.getenv("ANTHROPIC_WORKSPACE_ID"))
369 .authentication(AuthenticationConfig.builder()
370 .type(AuthenticationType.OIDC_FEDERATION)
371 .federationRuleId(System.getenv("ANTHROPIC_FEDERATION_RULE_ID"))
372 .serviceAccountId(System.getenv("ANTHROPIC_SERVICE_ACCOUNT_ID"))
373 .identityToken(IdentityTokenConfig.builder()
374 .source("value")
375 .path(googleIdentityToken)
376 .build())
377 .build())
378 .build()))
379 .build();
320380 
321381 var message = client.messages().create(MessageCreateParams.builder()
322 .model(Model.CLAUDE_OPUS_5_5)
323 .maxTokens(1024)
324 .addUserMessage("Hello from Cloud Run")
325 .build());
382 .model(Model.CLAUDE_OPUS_5_5)
383 .maxTokens(1024)
384 .addUserMessage("Hello from Cloud Run")
385 .build());
326386 
327387 IO.println(message.content());
328388 }
329389 ```
330390 
331 ```csharp C#
332 using Anthropic.Credentials;
333 // ...
334 
335 var credentials = new WorkloadIdentityCredentials(new WorkloadIdentityOptions
336 {
337 FederationRuleId = Environment.GetEnvironmentVariable("ANTHROPIC_FEDERATION_RULE_ID")!,
338 OrganizationId = Environment.GetEnvironmentVariable("ANTHROPIC_ORGANIZATION_ID"),
339 ServiceAccountId = Environment.GetEnvironmentVariable("ANTHROPIC_SERVICE_ACCOUNT_ID"),
340 WorkspaceId = Environment.GetEnvironmentVariable("ANTHROPIC_WORKSPACE_ID"),
341 IdentityTokenProvider = new MetadataTokenProvider(),
342 });
343 using var client = new AnthropicClient(new ClientOptions { Credentials = credentials });
344 
345 var message = await client.Messages.Create(new()
346 {
347 Model = Model.ClaudeOpus5_5,
348 MaxTokens = 1024,
349 Messages = [new UserMessageParam { Content = "Hello from Cloud Run" }],
350 });
351 foreach (var block in message.Content)
352 {
353 if (block.Value is TextBlock textBlock)
354 {
355 Console.WriteLine(textBlock.Text);
356 }
357 }
358 
359 class MetadataTokenProvider : IIdentityTokenProvider
360 {
361 private const string METADATA_URL =
362 "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://api.anthropic.com&format=full";
363 
364 private static readonly HttpClient httpClient = new()
365 {
366 DefaultRequestHeaders = { { "Metadata-Flavor", "Google" } },
367 };
368 
369 public async Task<string> GetIdentityTokenAsync(CancellationToken ct = default)
370 {
371 return await httpClient.GetStringAsync(METADATA_URL, ct);
372 }
373 }
374 ```
375 
376 ```bash CLI
377 # Write the Google-signed identity token to a file the CLI can read
378 export ANTHROPIC_IDENTITY_TOKEN_FILE=$(mktemp)
379 curl -sS -H "Metadata-Flavor: Google" \
380 "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://api.anthropic.com&format=full" \
381 > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
382 
383 # ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID,
384 # ANTHROPIC_SERVICE_ACCOUNT_ID, and ANTHROPIC_WORKSPACE_ID are read from the environment.
385 ant messages create \
386 --model claude-opus-5-5 \
387 --max-tokens 1024 \
388 --message '{role: user, content: "Hello from Cloud Run"}'
389 ```
390 
391391 ```php PHP
392392 use Anthropic\Client;
393393 use Anthropic\Lib\Credentials\CredentialResult;
from line 465
465465 | jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson'
466466```
467467 
468Check that `iss` is `https://accounts.google.com`, `aud` is `https://api.anthropic.com`, and `email` matches the value in your federation rule. Then run the exchange from the previous section. A successful exchange returns an `access_token` beginning with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason and see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange); the most common Google Cloud-side cause is the `email` claim missing (request the token with `format=full` so it is included).
468Check that `iss` is `https://accounts.google.com`, `aud` is `https://api.anthropic.com`, and `email` matches the value in your federation rule. Then run the exchange from the previous section. A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason and see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange); the most common Google Cloud-side cause is the `email` claim missing (request the token with `format=full` so it is included).
469469 
470470## Scope your rule
471471 
Feedback