okta changedmanage-claude/wif-providers/okta
Nearest release: v2.1.319, published 17 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+11added
Lines−11removed
From line
4
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits19to this page, all time
The whole hunk
from line 4, old and new numbered
/
from line 4
44description: Federate Okta service application identities to the Claude API with Workload Identity Federation.
55---
66
7Okta can act as a workload identity provider by issuing OIDC access tokens to a **service application** through the OAuth 2.0 `client_credentials` grant. Your workload authenticates to Okta (typically with `private_key_jwt`, so no shared secret is stored), receives a signed JSON Web Token (JWT), and exchanges that JWT with Anthropic for a short-lived access token.
7Okta can act as a workload identity provider by issuing OIDC access tokens to a **service application** through the OAuth 2.0 `client_credentials` grant. Your workload authenticates to Okta (typically with `private_key_jwt`, so you store no shared secret) and receives a signed JSON Web Token (JWT). It then exchanges that JWT with Anthropic for a short-lived access token.
88
99The Okta authorization server’s issuer URL takes the form `https://<your-domain>.okta.com/oauth2/<auth-server-id>`. If you use the built-in default server, the path is `/oauth2/default`.
1010
1111<Note>
12 You must use an Okta **custom authorization server** (including the `default` one). External parties cannot validate tokens issued directly by the Okta org authorization server (the `/oauth2/v1/token` endpoint with no authorization server ID in the path), because Okta does not publish signing keys for them.
12 You must use an Okta **custom authorization server** (including the `default` one). External parties cannot validate tokens that the Okta org authorization server issues directly, because Okta does not publish signing keys for them. The org authorization server’s token endpoint is `/oauth2/v1/token`, with no authorization server ID in the path.
1313</Note>
1414
15There are many ways to configure and authenticate to Okta that are outside the scope of this documentation. Ensure that your configuration and authentication mechanisms follow your company’s guidance and security practices.
15This page shows one way to configure and authenticate to Okta. Make sure your configuration and authentication mechanisms follow your company’s guidance and security practices.
1616
1717## Prerequisites
1818
19* Familiarity with [WIF concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
19* Familiarity with [Workload Identity Federation (WIF) concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
2020* An Okta organization with API Access Management enabled (required for custom authorization servers).
2121* Permission to create service accounts, federation issuers, and federation rules in the Claude Console for your Anthropic organization.
2222* A workload that can request a token from Okta’s `/v1/token` endpoint and reach `api.anthropic.com`.
from line 31
3131The exact navigation depends on your Okta org configuration and admin console version. The following numbered steps walk through one common path:
3232
33331. **Create a service app integration.** In the Okta Admin Console, create a new app integration of type **API Services** (OIDC, machine-to-machine). Note the generated **Client ID**.
342. **Configure client authentication.** For a keyless setup, select **Public key / Private key** (`private_key_jwt`) and register your workload’s public JWK. Alternatively, use a client secret if your environment can store one securely. For the following example you might need to disable the DPoP requirement on the application; ensure that your production setup adheres to your organization’s security requirements.
342. **Configure client authentication.** For a keyless setup, select **Public key / Private key** (`private_key_jwt`) and register your workload’s public JWK. Alternatively, use a client secret if your environment can store one securely. For the following example, you might need to disable the Demonstrating Proof of Possession (DPoP) requirement on the application. Make sure your production setup meets your organization’s security requirements.
35353. **Set the audience.** On your custom authorization server, set the audience to `https://api.anthropic.com` so issued access tokens carry that `aud` claim. Anthropic validates `aud` against this fixed value.
364. **Grant a scope.** On your custom authorization server, ensure at least one scope exists that the service app is allowed to request (for example, `anthropic.access`). Okta rejects `client_credentials` requests that do not include a granted scope.
364. **Grant a scope.** On your custom authorization server, ensure at least one scope exists that the service app can request (for example, `anthropic.access`). Okta rejects `client_credentials` requests that do not include a granted scope.
37375. **Create an access policy.** On your custom authorization server, create an access policy with at least one rule that allows your service app to request the scope you granted in step 4.
38386. **(Optional) Add custom claims.** If you want to match on something other than the client ID, add a claim to the access token in your authorization server’s **Claims** tab.
3939
from line 55
5555}
5656```
5757
58**Federation rule:** Match on the Okta `sub` claim, which is the service app’s Client ID. If you defined custom claims in Okta, you can match on those instead with the `claims` map or a CEL `condition`.
58**Federation rule:** Match on the Okta `sub` claim, which is the service app’s Client ID. If you defined custom claims in Okta, you can match on those instead with the `claims` map or a Common Expression Language (CEL) `condition`.
5959
6060```json
6161{
from line 74
7474
7575## Acquire a token and call the Claude API
7676
77Unlike platform-native providers (AWS, Google Cloud, Kubernetes), which make a token available inside the workload’s runtime (through a projected file or local metadata endpoint), Okta does not. Your workload must call Okta’s token endpoint to obtain a JWT, then pass that JWT to the Anthropic SDK as the identity token.
77Platform-native providers (AWS, Google Cloud, Kubernetes) make a token available inside the workload’s runtime, through a projected file or local metadata endpoint. Okta does not. Your workload must call Okta’s token endpoint to obtain a JWT, then pass that JWT to the SDK as the identity token.
7878
7979<CodeGroup>
8080 ```bash cURL
from line 494
494494 ```
495495</CodeGroup>
496496
497Pass your Okta token to `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`). Except in Java, where `IdentityTokenConfig` takes a token or a file path, that option takes your Okta fetch as a token provider. The Claude SDK calls it each time the Anthropic access token approaches expiry, so your Okta fetcher should return a fresh token on each call rather than caching one indefinitely. The `ant` CLI re-reads `ANTHROPIC_IDENTITY_TOKEN_FILE` on each exchange, so refresh that file on a timer for long-running shells.
497In the SDK, pass your Okta token to `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`). Where that option takes a token provider, the SDK calls the provider each time the Anthropic access token approaches expiry. The provider should return a fresh token on each call rather than caching one indefinitely. The `ant` CLI rereads `ANTHROPIC_IDENTITY_TOKEN_FILE` on each exchange, so refresh that file on a timer for long-running shells.
498498
499499## Verify the setup
500500
501A 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. The `issuer_url` must include the `/oauth2/<auth-server-id>` path, and the Okta org authorization server is not usable.
501A 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. Then 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. The `issuer_url` must include the `/oauth2/<auth-server-id>` path, and the Okta org authorization server is not usable.
502502
503503## Scope your rule
504504
from line 509
509509Lock the rule’s `match` block to the narrowest scope that fits your use case:
510510
511511* **Pin the exact Client ID:** Set `subject_prefix` to the service app’s full Client ID with no trailing `*`.
512* **Pin the audience:** Match the `audience` value you configured on the authorization server so tokens minted for a different audience are rejected.
512* **Pin the audience:** Match the `audience` value you configured on the authorization server so Anthropic rejects tokens issued for a different audience.
513513* **Match on custom claims:** For finer-grained scoping, add claims in the authorization server’s **Claims** tab and match them with the rule’s `claims` map or a CEL `condition`.
514514* **Use one rule for each service app:** Create a separate federation rule for each service app rather than sharing one rule across apps.
515515
No line in this hunk matches that.