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
/
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
No line in this hunk matches that.