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

okta changedmanage-claude/wif-providers/okta

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+101added
Lines−101removed
From line 113 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 113, old and new numbered
/
lines
from line 113
113113 }'
114114 ```
115115 
116 ```bash CLI
117 # 1. Request an access token from Okta and write it to a temp file.
118 export ANTHROPIC_IDENTITY_TOKEN_FILE=$(mktemp)
119 curl -sS "$OKTA_ISSUER/v1/token" \
120 -d grant_type=client_credentials \
121 -d scope=anthropic.access \
122 -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
123 --data-urlencode client_assertion="$SIGNED_CLIENT_ASSERTION" \
124 | jq -r .access_token > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
125 
126 # 2. Call the Claude API. The CLI reads ANTHROPIC_FEDERATION_RULE_ID,
127 # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID, ANTHROPIC_WORKSPACE_ID, and
128 # ANTHROPIC_IDENTITY_TOKEN_FILE and performs the exchange.
129 ant messages create \
130 --model claude-opus-5-5 \
131 --max-tokens 1024 \
132 --message '{role: user, content: "Hello, Claude"}'
133 ```
134 
116135 ```python Python
117136 import os
118137 import httpx2
from line 216
197216 }
198217 ```
199218 
219 ```csharp C#
220 using Anthropic.Credentials;
221 // ...
222 
223 var credentials = new WorkloadIdentityCredentials(new WorkloadIdentityOptions
224 {
225 FederationRuleId = Environment.GetEnvironmentVariable("ANTHROPIC_FEDERATION_RULE_ID")!,
226 OrganizationId = Environment.GetEnvironmentVariable("ANTHROPIC_ORGANIZATION_ID"),
227 ServiceAccountId = Environment.GetEnvironmentVariable("ANTHROPIC_SERVICE_ACCOUNT_ID"),
228 WorkspaceId = Environment.GetEnvironmentVariable("ANTHROPIC_WORKSPACE_ID"),
229 IdentityTokenProvider = new OktaTokenProvider(),
230 });
231 using var client = new AnthropicClient(new ClientOptions { Credentials = credentials });
232 
233 var message = await client.Messages.Create(new()
234 {
235 Model = Model.ClaudeOpus5_5,
236 MaxTokens = 1024,
237 Messages = [new UserMessageParam { Content = "Hello, Claude" }],
238 });
239 foreach (var block in message.Content)
240 {
241 if (block.Value is TextBlock textBlock)
242 {
243 Console.WriteLine(textBlock.Text);
244 }
245 }
246 
247 class OktaTokenProvider : IIdentityTokenProvider
248 {
249 private static readonly HttpClient Http = new();
250 
251 public async Task<string> GetIdentityTokenAsync(CancellationToken ct = default)
252 {
253 var form = new FormUrlEncodedContent(new Dictionary<string, string>
254 {
255 ["grant_type"] = "client_credentials",
256 ["scope"] = "anthropic.access",
257 ["client_assertion_type"] = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
258 // Build the RFC 7523 client_assertion JWT signed with your Okta app's private key
259 ["client_assertion"] = BuildSignedClientAssertion(),
260 });
261 var response = await Http.PostAsync(
262 $"{Environment.GetEnvironmentVariable("OKTA_ISSUER")}/v1/token", form, ct);
263 response.EnsureSuccessStatusCode();
264 using var json = await JsonDocument.ParseAsync(
265 await response.Content.ReadAsStreamAsync(ct), default, ct);
266 return json.RootElement.GetProperty("access_token").GetString()!;
267 }
268 }
269 ```
270 
200271 ```go Go
201272 package main
202273 
from line 359
288359 
289360 void main() throws Exception {
290361 var form = Map.of(
291 "grant_type", "client_credentials",
292 "scope", "anthropic.access",
293 "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
294 // Build the RFC 7523 client_assertion JWT signed with your Okta app's private key
295 "client_assertion", buildSignedClientAssertion())
296 .entrySet().stream()
297 .map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), UTF_8))
298 .collect(Collectors.joining("&"));
362 "grant_type", "client_credentials",
363 "scope", "anthropic.access",
364 "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
365 // Build the RFC 7523 client_assertion JWT signed with your Okta app's private key
366 "client_assertion", buildSignedClientAssertion())
367 .entrySet().stream()
368 .map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), UTF_8))
369 .collect(Collectors.joining("&"));
299370 var request = HttpRequest.newBuilder(URI.create(System.getenv("OKTA_ISSUER") + "/v1/token"))
300 .header("content-type", "application/x-www-form-urlencoded")
301 .POST(HttpRequest.BodyPublishers.ofString(form))
302 .build();
371 .header("content-type", "application/x-www-form-urlencoded")
372 .POST(HttpRequest.BodyPublishers.ofString(form))
373 .build();
303374 
304375 // The Java SDK takes the token itself or a file path, not a function; with
305376 // source("value"), path(...) holds the token. The SDK sends that same token
from line 382
311382 String oktaToken = new ObjectMapper().readTree(response.body()).get("access_token").asText();
312383 
313384 AnthropicClient client = AnthropicOkHttpClient.builder()
314 .configurationProvider(InMemoryProfileConfigProvider.of(ProfileConfig.builder()
315 .organizationId(System.getenv("ANTHROPIC_ORGANIZATION_ID"))
316 .workspaceId(System.getenv("ANTHROPIC_WORKSPACE_ID"))
317 .authentication(AuthenticationConfig.builder()
318 .type(AuthenticationType.OIDC_FEDERATION)
319 .federationRuleId(System.getenv("ANTHROPIC_FEDERATION_RULE_ID"))
320 .serviceAccountId(System.getenv("ANTHROPIC_SERVICE_ACCOUNT_ID"))
321 .identityToken(IdentityTokenConfig.builder()
322 .source("value")
323 .path(oktaToken)
324 .build())
325 .build())
326 .build()))
327 .build();
385 .configurationProvider(InMemoryProfileConfigProvider.of(ProfileConfig.builder()
386 .organizationId(System.getenv("ANTHROPIC_ORGANIZATION_ID"))
387 .workspaceId(System.getenv("ANTHROPIC_WORKSPACE_ID"))
388 .authentication(AuthenticationConfig.builder()
389 .type(AuthenticationType.OIDC_FEDERATION)
390 .federationRuleId(System.getenv("ANTHROPIC_FEDERATION_RULE_ID"))
391 .serviceAccountId(System.getenv("ANTHROPIC_SERVICE_ACCOUNT_ID"))
392 .identityToken(IdentityTokenConfig.builder()
393 .source("value")
394 .path(oktaToken)
395 .build())
396 .build())
397 .build()))
398 .build();
328399 
329400 var message = client.messages().create(MessageCreateParams.builder()
330 .model(Model.CLAUDE_OPUS_5_5)
331 .maxTokens(1024)
332 .addUserMessage("Hello, Claude")
333 .build());
401 .model(Model.CLAUDE_OPUS_5_5)
402 .maxTokens(1024)
403 .addUserMessage("Hello, Claude")
404 .build());
334405 
335406 IO.println(message.content());
336407 }
337408 ```
338409 
339 ```csharp C#
340 using Anthropic.Credentials;
341 // ...
342 
343 var credentials = new WorkloadIdentityCredentials(new WorkloadIdentityOptions
344 {
345 FederationRuleId = Environment.GetEnvironmentVariable("ANTHROPIC_FEDERATION_RULE_ID")!,
346 OrganizationId = Environment.GetEnvironmentVariable("ANTHROPIC_ORGANIZATION_ID"),
347 ServiceAccountId = Environment.GetEnvironmentVariable("ANTHROPIC_SERVICE_ACCOUNT_ID"),
348 WorkspaceId = Environment.GetEnvironmentVariable("ANTHROPIC_WORKSPACE_ID"),
349 IdentityTokenProvider = new OktaTokenProvider(),
350 });
351 using var client = new AnthropicClient(new ClientOptions { Credentials = credentials });
352 
353 var message = await client.Messages.Create(new()
354 {
355 Model = Model.ClaudeOpus5_5,
356 MaxTokens = 1024,
357 Messages = [new UserMessageParam { Content = "Hello, Claude" }],
358 });
359 foreach (var block in message.Content)
360 {
361 if (block.Value is TextBlock textBlock)
362 {
363 Console.WriteLine(textBlock.Text);
364 }
365 }
366 
367 class OktaTokenProvider : IIdentityTokenProvider
368 {
369 private static readonly HttpClient Http = new();
370 
371 public async Task<string> GetIdentityTokenAsync(CancellationToken ct = default)
372 {
373 var form = new FormUrlEncodedContent(new Dictionary<string, string>
374 {
375 ["grant_type"] = "client_credentials",
376 ["scope"] = "anthropic.access",
377 ["client_assertion_type"] = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
378 // Build the RFC 7523 client_assertion JWT signed with your Okta app's private key
379 ["client_assertion"] = BuildSignedClientAssertion(),
380 });
381 var response = await Http.PostAsync(
382 $"{Environment.GetEnvironmentVariable("OKTA_ISSUER")}/v1/token", form, ct);
383 response.EnsureSuccessStatusCode();
384 using var json = await JsonDocument.ParseAsync(
385 await response.Content.ReadAsStreamAsync(ct), default, ct);
386 return json.RootElement.GetProperty("access_token").GetString()!;
387 }
388 }
389 ```
390 
391 ```bash CLI
392 # 1. Request an access token from Okta and write it to a temp file.
393 export ANTHROPIC_IDENTITY_TOKEN_FILE=$(mktemp)
394 curl -sS "$OKTA_ISSUER/v1/token" \
395 -d grant_type=client_credentials \
396 -d scope=anthropic.access \
397 -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
398 --data-urlencode client_assertion="$SIGNED_CLIENT_ASSERTION" \
399 | jq -r .access_token > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
400 
401 # 2. Call the Claude API. The CLI reads ANTHROPIC_FEDERATION_RULE_ID,
402 # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID, ANTHROPIC_WORKSPACE_ID, and
403 # ANTHROPIC_IDENTITY_TOKEN_FILE and performs the exchange.
404 ant messages create \
405 --model claude-opus-5-5 \
406 --max-tokens 1024 \
407 --message '{role: user, content: "Hello, Claude"}'
408 ```
409 
410410 ```php PHP
411411 use Anthropic\Client;
412412 use Anthropic\Lib\Credentials\CredentialResult;
from line 496
496496 
497497## Verify the setup
498498 
499A 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 Okta-side cause is an `issuer_url` mismatch (it must include the `/oauth2/<auth-server-id>` path; the Okta org authorization server is not usable).
499A 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 Okta-side cause is an `issuer_url` mismatch (it must include the `/oauth2/<auth-server-id>` path; the Okta org authorization server is not usable).
500500 
501501## Scope your rule
502502 
Feedback