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

gcp changedmanage-claude/wif-providers/gcp

Nearest release: v2.1.302, published 12 hours after 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+76added
Lines−42removed
From line 126 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits12to this page, all time

The whole hunk

from line 126, old and new numbered
/
lines
from line 126
126126 
127127## Acquire and use the token
128128 
129Inside your Google Cloud workload, fetch the identity token from the metadata server, exchange it at `POST /v1/oauth/token`, and use the returned bearer token to call the Claude API. The Claude SDK handles the exchange and refresh loop for you when you pass a callable that returns a fresh identity token from the metadata server to `identity_token_provider` (typescript, php: `identityTokenProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `federationTokenProvider`), as shown in the following examples.
129Inside your Google Cloud workload, fetch the identity token from the metadata server, exchange it at `POST /v1/oauth/token`, and use the returned bearer token to call the Claude API. The Claude SDK handles the exchange and refresh loop for you when you supply `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `IdentityTokenConfig`), as shown in the following examples. Except in Java (see the comment in that example), that option takes a token provider that returns a fresh identity token from the metadata server.
130130 
131131<CodeGroup>
132132 ```bash cURL
from line 276
276276 ```
277277 
278278 ```java Java
279 HttpClient http = HttpClient.newHttpClient();
280 HttpRequest metadataRequest = HttpRequest.newBuilder()
281 .uri(URI.create("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://api.anthropic.com&format=full"))
282 .header("Metadata-Flavor", "Google")
283 .build();
279 import com.anthropic.config.AuthenticationConfig;
280 import com.anthropic.config.AuthenticationType;
281 import com.anthropic.config.IdentityTokenConfig;
282 import com.anthropic.config.InMemoryProfileConfigProvider;
283 import com.anthropic.config.ProfileConfig;
284 // ...
285 import java.net.URI;
286 import java.net.http.HttpClient;
287 import java.net.http.HttpRequest;
288 import java.net.http.HttpResponse;
284289 
285 IdentityTokenProvider fetchGoogleIdentityToken = () -> {
286 try {
287 return http.send(metadataRequest, HttpResponse.BodyHandlers.ofString()).body();
288 } catch (Exception e) {
289 throw new RuntimeException(e);
290 }
291 };
290 void main() throws Exception {
291 HttpClient http = HttpClient.newHttpClient();
292 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();
292296 
293 AnthropicClient client = AnthropicOkHttpClient.builder()
294 .federationTokenProvider(
295 fetchGoogleIdentityToken,
296 System.getenv("ANTHROPIC_FEDERATION_RULE_ID"),
297 System.getenv("ANTHROPIC_ORGANIZATION_ID"),
298 System.getenv("ANTHROPIC_SERVICE_ACCOUNT_ID"))
299 .build();
297 // The Java SDK takes the token itself or a file path, not a function; with
298 // source("value"), path(...) holds the token. The SDK sends that same token
299 // at every refresh of the Anthropic access token, which fails once it has
300 // expired or, if it has a jti claim, been used. For a longer-running
301 // process, pass source("file") and write a new token to the file before
302 // each refresh.
303 String googleIdentityToken = http.send(metadataRequest, HttpResponse.BodyHandlers.ofString()).body();
300304 
301 var message = client.messages().create(MessageCreateParams.builder()
302 .model(Model.CLAUDE_OPUS_5_5)
303 .maxTokens(1024)
304 .addUserMessage("Hello from Cloud Run")
305 .build());
305 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();
306320 
307 IO.println(message.content());
321 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());
326 
327 IO.println(message.content());
328 }
308329 ```
309330 
310331 ```csharp C#
from line 391
370391 
371392 ```php PHP
372393 use Anthropic\Client;
373 use Anthropic\Credentials\WorkloadIdentityCredentials;
394 use Anthropic\Lib\Credentials\CredentialResult;
395 use Anthropic\Lib\Credentials\IdentityTokenProvider;
396 use Anthropic\Lib\Credentials\TokenCache;
397 use Anthropic\Lib\Credentials\WorkloadIdentityCredentials;
374398 
375399 const METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://api.anthropic.com&format=full';
376400 
377 $context = stream_context_create([
378 'http' => ['header' => "Metadata-Flavor: Google\r\n"],
379 ]);
401 class GoogleIdentityToken implements IdentityTokenProvider
402 {
403 public function getIdentityToken(): string
404 {
405 $context = stream_context_create([
406 'http' => ['header' => "Metadata-Flavor: Google\r\n"],
407 ]);
380408 
381 $credentials = new WorkloadIdentityCredentials(
382 identityTokenProvider: fn() => file_get_contents(METADATA_URL, false, $context),
383 federationRuleId: getenv('ANTHROPIC_FEDERATION_RULE_ID'),
384 organizationId: getenv('ANTHROPIC_ORGANIZATION_ID'),
385 serviceAccountId: getenv('ANTHROPIC_SERVICE_ACCOUNT_ID'),
386 workspaceId: getenv('ANTHROPIC_WORKSPACE_ID') ?: null,
409 return file_get_contents(METADATA_URL, false, $context);
410 }
411 }
412 
413 $credentials = new CredentialResult(
414 provider: new TokenCache(new WorkloadIdentityCredentials(
415 identityProvider: new GoogleIdentityToken(),
416 federationRuleId: getenv('ANTHROPIC_FEDERATION_RULE_ID'),
417 organizationId: getenv('ANTHROPIC_ORGANIZATION_ID'),
418 serviceAccountId: getenv('ANTHROPIC_SERVICE_ACCOUNT_ID'),
419 workspaceId: getenv('ANTHROPIC_WORKSPACE_ID') ?: null,
420 )),
387421 );
388422 $client = new Client(credentials: $credentials);
389423 
from line 454
420454 ```
421455</CodeGroup>
422456 
423Google identity tokens expire after roughly one hour. The SDK re-invokes the token provider and re-exchanges automatically before expiry. For shell scripts that run longer than the access token's `expires_in`, refresh on a timer and repeat the exchange.
457Google identity tokens expire after roughly one hour. Except in Java (see the comment in that example), the SDK re-invokes the token provider and re-exchanges automatically before expiry. For shell scripts that run longer than the access token's `expires_in`, refresh on a timer and repeat the exchange.
424458 
425459## Verify the setup
426460 
Feedback