---
title: Использование WIF с Okta
url: https://platform.claude.com/docs/ru/manage-claude/wif-providers/okta
description: Федерация идентификаторов сервисных приложений Okta с Claude API с помощью Workload Identity Federation.
---

Okta может выступать в роли поставщика идентификации рабочих нагрузок, выдавая токены доступа OIDC **сервисному приложению** (service application) через грант OAuth 2.0 `client_credentials`. Ваша рабочая нагрузка аутентифицируется в Okta (обычно с помощью `private_key_jwt`, поэтому общий секрет не хранится), получает подписанный «JSON Web Token» (веб-токен JSON), или JWT, и обменивает этот JWT у Anthropic на краткосрочный токен доступа.

URL издателя сервера авторизации Okta имеет вид `https://<your-domain>.okta.com/oauth2/<auth-server-id>`. Если вы используете встроенный сервер по умолчанию, путь будет `/oauth2/default`.

<Note>
  Вы должны использовать **пользовательский сервер авторизации** (custom authorization server) Okta (включая сервер `default`). Токены, выданные непосредственно сервером авторизации организации Okta (конечная точка `/oauth2/v1/token` без идентификатора сервера авторизации в пути), не могут быть проверены внешними сторонами, поскольку Okta не публикует для них ключи подписи.
</Note>

Существует множество способов настройки Okta и аутентификации в ней, которые выходят за рамки данной документации. Убедитесь, что ваши механизмы настройки и аутентификации соответствуют рекомендациям и практикам безопасности вашей компании.

## Предварительные требования

* Знакомство с [концепциями WIF](https://platform.claude.com/docs/ru/manage-claude/workload-identity-federation#concepts): сервисные учётные записи, издатели федерации и правила федерации.
* Организация Okta с включённым API Access Management (требуется для пользовательских серверов авторизации).
* Разрешение на создание сервисных учётных записей, издателей федерации и правил федерации в Claude Console для вашей организации Anthropic.
* Рабочая нагрузка, которая может запрашивать токен у конечной точки Okta `/v1/token` и обращаться к `api.anthropic.com`.

## Настройка Okta

В общих чертах вам необходимо:

1. Создать сервисное приложение Okta.
2. Настроить сервер авторизации по умолчанию (или создать новый пользовательский сервер авторизации) с аудиторией, областью (scope), политикой доступа и любыми пользовательскими утверждениями (claims), по которым вы хотите выполнять сопоставление.

Точная навигация зависит от конфигурации вашей организации Okta и версии консоли администратора. Следующие пронумерованные шаги описывают один из распространённых путей:

1. **Создайте интеграцию сервисного приложения.** В Okta Admin Console создайте новую интеграцию приложения типа **API Services** (OIDC, machine-to-machine). Запишите сгенерированный **Client ID**.
2. **Настройте аутентификацию клиента.** Для настройки без ключей выберите **Public key / Private key** (`private_key_jwt`) и зарегистрируйте публичный JWK вашей рабочей нагрузки. В качестве альтернативы используйте секрет клиента, если ваша среда может безопасно его хранить. Для следующего примера вам может потребоваться отключить требование DPoP для приложения; убедитесь, что ваша производственная конфигурация соответствует требованиям безопасности вашей организации.
3. **Задайте аудиторию.** На вашем пользовательском сервере авторизации установите аудиторию `https://api.anthropic.com`, чтобы выдаваемые токены доступа содержали это утверждение `aud`. Anthropic проверяет `aud` на соответствие этому фиксированному значению.
4. **Предоставьте область.** На вашем пользовательском сервере авторизации убедитесь, что существует хотя бы одна область, которую сервисному приложению разрешено запрашивать (например, `anthropic.access`). Okta отклоняет запросы `client_credentials`, не включающие предоставленную область.
5. **Создайте политику доступа.** На вашем пользовательском сервере авторизации создайте политику доступа хотя бы с одним правилом, разрешающим вашему сервисному приложению запрашивать область, предоставленную на шаге 4.
6. **(Необязательно) Добавьте пользовательские утверждения.** Если вы хотите выполнять сопоставление по чему-либо, кроме идентификатора клиента, добавьте утверждение в токен доступа на вкладке **Claims** вашего сервера авторизации.

Для сервисного приложения, использующего `client_credentials`, Okta устанавливает утверждение `sub` выданного токена доступа равным **Client ID** приложения, а `iss` — равным URL издателя сервера авторизации.

## Настройка Anthropic

В Claude Console перейдите на страницу [Workload identity](https://platform.claude.com/settings/workload-identity-federation) (`platform.claude.com/settings/workload-identity-federation`), нажмите **Connect workload** и выберите **Custom OIDC**. Мастер проведёт вас через регистрацию издателя, создание сервисной учётной записи и создание правила федерации.

Мастер создаёт эти ресурсы за вас. Используйте следующие значения независимо от того, вводите ли вы их в мастере или отправляете в [Admin API](https://platform.claude.com/docs/ru/manage-claude/wif-admin-api):

**Издатель федерации:** используйте URL вашего пользовательского сервера авторизации Okta и режим обнаружения (discovery). Anthropic считывает документ обнаружения Okta `.well-known/openid-configuration` и получает JWKS по адресу `jwks_uri`, который в нём указан.

```json
{
  "name": "okta-prod",
  "issuer_url": "https://acme.okta.com/oauth2/aus1a2b3c4d5e6f7g8h9",
  "jwks": { "type": "discovery" }
}
```

**Правило федерации:** выполняйте сопоставление по утверждению Okta `sub`, которое является Client ID сервисного приложения. Если вы определили пользовательские утверждения в Okta, вы можете вместо этого выполнять сопоставление по ним с помощью карты `claims` или CEL-выражения `condition`.

```json
{
  "name": "okta-pipeline",
  "issuer_id": "fdis_...",
  "match": {
    "subject_prefix": "0oa1b2c3d4e5f6g7h8i9",
    "audience": "https://api.anthropic.com"
  },
  "target": { "type": "service_account", "service_account_id": "svac_..." },
  "workspace_id": "wrkspc_...",
  "oauth_scope": "workspace:developer",
  "token_lifetime_seconds": 600
}
```

## Получение токена и вызов Claude API

В отличие от платформенно-нативных поставщиков (AWS, Google Cloud, Kubernetes), которые делают токен доступным внутри среды выполнения рабочей нагрузки (через проецируемый файл или локальную конечную точку метаданных), Okta этого не делает. Ваша рабочая нагрузка должна вызвать конечную точку токенов Okta, чтобы получить JWT, а затем передать этот JWT в Anthropic SDK в качестве токена идентификации.

<CodeGroup>
  ```bash cURL
  # 1. Запросите токен доступа у Okta (client_credentials с private_key_jwt).
  OKTA_JWT=$(curl -sS "https://acme.okta.com/oauth2/aus1a2b3c4d5e6f7g8h9/v1/token" \
    -d grant_type=client_credentials \
    -d scope=anthropic.access \
    -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
    --data-urlencode client_assertion="$SIGNED_CLIENT_ASSERTION" \
    | jq -r .access_token)

  # 2. Обменяйте JWT от Okta на токен доступа Anthropic.
  ACCESS_TOKEN=$(curl -sS https://api.anthropic.com/v1/oauth/token \
    -H "content-type: application/json" \
    -d @- <<JSON | jq -r .access_token
  {
    "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
    "assertion": "$OKTA_JWT",
    "federation_rule_id": "$ANTHROPIC_FEDERATION_RULE_ID",
    "organization_id": "$ANTHROPIC_ORGANIZATION_ID",
    "service_account_id": "$ANTHROPIC_SERVICE_ACCOUNT_ID",
    "workspace_id": "$ANTHROPIC_WORKSPACE_ID"
  }
  JSON
  )

  # 3. Вызовите Claude API.
  curl https://api.anthropic.com/v1/messages \
    -H "authorization: Bearer $ACCESS_TOKEN" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{"model": "claude-opus-5-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello, Claude"}]}' \
    | jq -r '.content[] | select(.type == "text") | .text'
  ```

  ```python Python
  import os
  import httpx2
  import anthropic
  from anthropic import WorkloadIdentityCredentials


  def fetch_okta_token() -> str:
      response = httpx2.post(
          f"{os.environ['OKTA_ISSUER']}/v1/token",
          data={
              "grant_type": "client_credentials",
              "scope": "anthropic.access",
              "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
              # Создайте JWT client_assertion по RFC 7523, подписанный закрытым ключом вашего приложения Okta
              "client_assertion": build_signed_client_assertion(),
          },
      )
      response.raise_for_status()
      return response.json()["access_token"]


  client = anthropic.Anthropic(
      credentials=WorkloadIdentityCredentials(
          identity_token_provider=fetch_okta_token,
          federation_rule_id=os.environ["ANTHROPIC_FEDERATION_RULE_ID"],
          organization_id=os.environ["ANTHROPIC_ORGANIZATION_ID"],
          service_account_id=os.environ["ANTHROPIC_SERVICE_ACCOUNT_ID"],
          workspace_id=os.environ.get("ANTHROPIC_WORKSPACE_ID"),
      ),
  )

  message = client.messages.create(
      model="claude-opus-5-5",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Hello, Claude"}],
  )
  print(next(block.text for block in message.content if block.type == "text"))
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";
  import { oidcFederationProvider } from "@anthropic-ai/sdk/lib/credentials/oidc-federation";

  async function fetchOktaToken(): Promise<string> {
    const response = await fetch(`${process.env.OKTA_ISSUER}/v1/token`, {
      method: "POST",
      headers: { "content-type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams({
        grant_type: "client_credentials",
        scope: "anthropic.access",
        client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
        // Создайте JWT client_assertion по RFC 7523, подписанный закрытым ключом вашего приложения Okta
        client_assertion: buildSignedClientAssertion()
      })
    });
    const body = (await response.json()) as { access_token: string };
    return body.access_token;
  }

  const client = new Anthropic({
    credentials: oidcFederationProvider({
      identityTokenProvider: fetchOktaToken,
      federationRuleId: process.env.ANTHROPIC_FEDERATION_RULE_ID!,
      organizationId: process.env.ANTHROPIC_ORGANIZATION_ID!,
      serviceAccountId: process.env.ANTHROPIC_SERVICE_ACCOUNT_ID,
      workspaceId: process.env.ANTHROPIC_WORKSPACE_ID,
      baseURL: "https://api.anthropic.com",
      fetch
    })
  });

  const message = await client.messages.create({
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello, Claude" }]
  });
  for (const block of message.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  ```

  ```go Go
  package main

  import (
  	"context"
  	"encoding/json"
  	"fmt"
  	"net/http"
  	"net/url"
  	"os"
  	"strings"

  	"github.com/anthropics/anthropic-sdk-go"
  	"github.com/anthropics/anthropic-sdk-go/option"
  )

  func fetchOktaToken(ctx context.Context) (string, error) {
  	form := url.Values{
  		"grant_type":            {"client_credentials"},
  		"scope":                 {"anthropic.access"},
  		"client_assertion_type": {"urn:ietf:params:oauth:client-assertion-type:jwt-bearer"},
  		// Создайте JWT client_assertion по RFC 7523, подписанный закрытым ключом вашего приложения Okta
  		"client_assertion": {buildSignedClientAssertion()},
  	}
  	req, err := http.NewRequestWithContext(ctx, http.MethodPost,
  		os.Getenv("OKTA_ISSUER")+"/v1/token", strings.NewReader(form.Encode()))
  	if err != nil {
  		return "", err
  	}
  	req.Header.Set("content-type", "application/x-www-form-urlencoded")
  	resp, err := http.DefaultClient.Do(req)
  	if err != nil {
  		return "", err
  	}
  	defer resp.Body.Close()
  	var body struct {
  		AccessToken string `json:"access_token"`
  	}
  	if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
  		return "", err
  	}
  	return body.AccessToken, nil
  }

  func main() {
  	client := anthropic.NewClient(
  		option.WithFederationTokenProvider(option.IdentityTokenFunc(fetchOktaToken), option.FederationOptions{
  			FederationRuleID: os.Getenv("ANTHROPIC_FEDERATION_RULE_ID"),
  			OrganizationID:   os.Getenv("ANTHROPIC_ORGANIZATION_ID"),
  			ServiceAccountID: os.Getenv("ANTHROPIC_SERVICE_ACCOUNT_ID"),
  			WorkspaceID:      os.Getenv("ANTHROPIC_WORKSPACE_ID"),
  		}),
  	)
  	message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 1024,
  		Messages: []anthropic.MessageParam{
  			anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Claude")),
  		},
  	})
  	if err != nil {
  		panic(err)
  	}
  	for _, block := range message.Content {
  		if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
  			fmt.Println(textBlock.Text)
  			break
  		}
  	}
  }
  ```

  ```java Java
  import com.anthropic.config.AuthenticationConfig;
  import com.anthropic.config.AuthenticationType;
  import com.anthropic.config.IdentityTokenConfig;
  import com.anthropic.config.InMemoryProfileConfigProvider;
  import com.anthropic.config.ProfileConfig;
  // ...
  import com.fasterxml.jackson.databind.ObjectMapper;
  import java.net.URI;
  import java.net.URLEncoder;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.util.Map;
  import java.util.stream.Collectors;
  import static java.nio.charset.StandardCharsets.UTF_8;

  void main() throws Exception {
      var form = Map.of(
                      "grant_type", "client_credentials",
                      "scope", "anthropic.access",
                      "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
                      // Создайте JWT client_assertion по RFC 7523, подписанный закрытым ключом вашего приложения Okta
                      "client_assertion", buildSignedClientAssertion())
              .entrySet().stream()
              .map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), UTF_8))
              .collect(Collectors.joining("&"));
      var request = HttpRequest.newBuilder(URI.create(System.getenv("OKTA_ISSUER") + "/v1/token"))
              .header("content-type", "application/x-www-form-urlencoded")
              .POST(HttpRequest.BodyPublishers.ofString(form))
              .build();

      // Java SDK принимает сам токен или путь к файлу, а не функцию; при
      // source("value") path(...) содержит токен. SDK отправляет тот же токен
      // при каждом обновлении токена доступа Anthropic, что завершится ошибкой, когда он
      // истечёт или, если у него есть утверждение jti, будет использован. Для долго работающих
      // процессов передайте source("file") и записывайте новый токен в файл перед
      // каждым обновлением.
      var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
      String oktaToken = new ObjectMapper().readTree(response.body()).get("access_token").asText();

      AnthropicClient client = AnthropicOkHttpClient.builder()
              .configurationProvider(InMemoryProfileConfigProvider.of(ProfileConfig.builder()
                      .organizationId(System.getenv("ANTHROPIC_ORGANIZATION_ID"))
                      .workspaceId(System.getenv("ANTHROPIC_WORKSPACE_ID"))
                      .authentication(AuthenticationConfig.builder()
                              .type(AuthenticationType.OIDC_FEDERATION)
                              .federationRuleId(System.getenv("ANTHROPIC_FEDERATION_RULE_ID"))
                              .serviceAccountId(System.getenv("ANTHROPIC_SERVICE_ACCOUNT_ID"))
                              .identityToken(IdentityTokenConfig.builder()
                                      .source("value")
                                      .path(oktaToken)
                                      .build())
                              .build())
                      .build()))
              .build();

      var message = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024)
              .addUserMessage("Hello, Claude")
              .build());

      IO.println(message.content());
  }
  ```

  ```csharp C#
  using Anthropic.Credentials;
  // ...

  var credentials = new WorkloadIdentityCredentials(new WorkloadIdentityOptions
  {
      FederationRuleId = Environment.GetEnvironmentVariable("ANTHROPIC_FEDERATION_RULE_ID")!,
      OrganizationId = Environment.GetEnvironmentVariable("ANTHROPIC_ORGANIZATION_ID"),
      ServiceAccountId = Environment.GetEnvironmentVariable("ANTHROPIC_SERVICE_ACCOUNT_ID"),
      WorkspaceId = Environment.GetEnvironmentVariable("ANTHROPIC_WORKSPACE_ID"),
      IdentityTokenProvider = new OktaTokenProvider(),
  });
  using var client = new AnthropicClient(new ClientOptions { Credentials = credentials });

  var message = await client.Messages.Create(new()
  {
      Model = Model.ClaudeOpus5_5,
      MaxTokens = 1024,
      Messages = [new() { Role = Role.User, Content = "Hello, Claude" }],
  });
  foreach (var block in message.Content)
  {
      if (block.Value is TextBlock textBlock)
      {
          Console.WriteLine(textBlock.Text);
      }
  }

  class OktaTokenProvider : IIdentityTokenProvider
  {
      private static readonly HttpClient Http = new();

      public async Task<string> GetIdentityTokenAsync(CancellationToken ct = default)
      {
          var form = new FormUrlEncodedContent(new Dictionary<string, string>
          {
              ["grant_type"] = "client_credentials",
              ["scope"] = "anthropic.access",
              ["client_assertion_type"] = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
              // Сформируйте JWT client_assertion по RFC 7523, подписанный закрытым ключом вашего приложения Okta
              ["client_assertion"] = BuildSignedClientAssertion(),
          });
          var response = await Http.PostAsync(
              $"{Environment.GetEnvironmentVariable("OKTA_ISSUER")}/v1/token", form, ct);
          response.EnsureSuccessStatusCode();
          using var json = await JsonDocument.ParseAsync(
              await response.Content.ReadAsStreamAsync(ct), default, ct);
          return json.RootElement.GetProperty("access_token").GetString()!;
      }
  }
  ```

  ```bash CLI
  # 1. Запросите токен доступа у Okta и запишите его во временный файл.
  ANTHROPIC_IDENTITY_TOKEN_FILE=$(mktemp)
  curl -sS "$OKTA_ISSUER/v1/token" \
    -d grant_type=client_credentials \
    -d scope=anthropic.access \
    -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
    --data-urlencode client_assertion="$SIGNED_CLIENT_ASSERTION" \
    | jq -r .access_token > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
  export ANTHROPIC_IDENTITY_TOKEN_FILE

  # 2. Вызовите Claude API. CLI считывает ANTHROPIC_FEDERATION_RULE_ID,
  # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID, ANTHROPIC_WORKSPACE_ID и
  # ANTHROPIC_IDENTITY_TOKEN_FILE и выполняет обмен.
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "Hello, Claude"}'
  ```

  ```php PHP
  use Anthropic\Client;
  use Anthropic\Lib\Credentials\CredentialResult;
  use Anthropic\Lib\Credentials\IdentityTokenProvider;
  use Anthropic\Lib\Credentials\TokenCache;
  use Anthropic\Lib\Credentials\WorkloadIdentityCredentials;

  class OktaIdentityToken implements IdentityTokenProvider
  {
      public function getIdentityToken(): string
      {
          $ch = curl_init(getenv('OKTA_ISSUER') . '/v1/token');
          curl_setopt_array($ch, [
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_POSTFIELDS => http_build_query([
                  'grant_type' => 'client_credentials',
                  'scope' => 'anthropic.access',
                  'client_assertion_type' => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
                  // Создайте JWT client_assertion по RFC 7523, подписанный закрытым ключом вашего приложения Okta
                  'client_assertion' => buildSignedClientAssertion(),
              ]),
          ]);
          $body = json_decode(curl_exec($ch), true);
          curl_close($ch);
          return $body['access_token'];
      }
  }

  $client = new Client(
      credentials: new CredentialResult(
          provider: new TokenCache(new WorkloadIdentityCredentials(
              identityProvider: new OktaIdentityToken(),
              federationRuleId: getenv('ANTHROPIC_FEDERATION_RULE_ID'),
              organizationId: getenv('ANTHROPIC_ORGANIZATION_ID'),
              serviceAccountId: getenv('ANTHROPIC_SERVICE_ACCOUNT_ID'),
              workspaceId: getenv('ANTHROPIC_WORKSPACE_ID') ?: null,
          )),
      ),
  );

  $message = $client->messages->create(
      model: 'claude-opus-5-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
  );
  echo array_find($message->content, static fn ($block): bool => $block->type === 'text')->text, PHP_EOL;
  ```

  ```ruby Ruby
  require "anthropic"
  require "json"
  require "net/http"

  def fetch_okta_token
    uri = URI("#{ENV.fetch('OKTA_ISSUER')}/v1/token")
    response = Net::HTTP.post_form(
      uri,
      "grant_type" => "client_credentials",
      "scope" => "anthropic.access",
      "client_assertion_type" => "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
      # Создайте JWT client_assertion по RFC 7523, подписанный закрытым ключом вашего приложения Okta
      "client_assertion" => build_signed_client_assertion
    )
    JSON.parse(response.body).fetch("access_token")
  end

  client = Anthropic::Client.new(
    credentials: Anthropic::WorkloadIdentityCredentials.new(
      identity_token_provider: -> { fetch_okta_token },
      federation_rule_id: ENV.fetch("ANTHROPIC_FEDERATION_RULE_ID"),
      organization_id: ENV.fetch("ANTHROPIC_ORGANIZATION_ID"),
      service_account_id: ENV.fetch("ANTHROPIC_SERVICE_ACCOUNT_ID"),
      workspace_id: ENV["ANTHROPIC_WORKSPACE_ID"]
    )
  )

  message = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}]
  )
  puts message.content.find { it.type == :text }.text
  ```
</CodeGroup>

За исключением Java (см. комментарий в этом примере), пример SDK передаёт вашу функцию получения токена Okta в `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `IdentityTokenConfig`) в качестве поставщика токенов. Claude SDK вызывает её каждый раз, когда срок действия токена доступа Anthropic подходит к концу, поэтому ваша функция получения токена Okta должна возвращать новый токен при каждом вызове, а не кэшировать один токен бессрочно. CLI `ant` повторно считывает `ANTHROPIC_IDENTITY_TOKEN_FILE` при каждом обмене, поэтому для долго работающих оболочек обновляйте этот файл по таймеру.

## Проверка настройки

Успешный обмен возвращает `access_token`, начинающийся с `sk-ant-oat01-`, и значение `expires_in` в секундах. Если обмен завершается непрозрачным ответом `401` `authentication_error` (сообщение `Authentication failed`), проверьте причину отказа на [странице истории аутентификации](https://platform.claude.com/settings/workload-identity-federation?tab=history) в Claude Console и ознакомьтесь с разделом [Устранение неполадок при неудачном обмене](https://platform.claude.com/docs/ru/manage-claude/wif-reference#troubleshoot-a-failed-exchange); наиболее распространённая причина на стороне Okta — несоответствие `issuer_url` (он должен включать путь `/oauth2/<auth-server-id>`; сервер авторизации организации Okta использовать нельзя).

## Ограничение области действия правила

<Warning>
  Несколько сервисных приложений в рамках одного сервера авторизации Okta используют одного и того же издателя. Правило, в котором опущен `subject_prefix`, соответствует каждому сервисному приложению на этом сервере, поэтому любая команда, способная зарегистрировать такое приложение, может получить федеративный токен Anthropic.
</Warning>

Ограничьте блок `match` правила самой узкой областью, подходящей для вашего сценария использования:

* **Закрепите точный Client ID:** установите `subject_prefix` равным полному Client ID сервисного приложения без завершающего `*`.
* **Закрепите аудиторию:** сопоставляйте значение `audience`, настроенное на сервере авторизации, чтобы токены, выпущенные для другой аудитории, отклонялись.
* **Сопоставляйте по пользовательским утверждениям:** для более детального ограничения добавьте утверждения на вкладке **Claims** сервера авторизации и сопоставляйте их с помощью карты `claims` правила или CEL-выражения `condition`.
* **Используйте одно правило на сервисное приложение:** создавайте отдельное правило федерации для каждого сервисного приложения, а не используйте одно правило для нескольких приложений.

## Следующие шаги

* Ознакомьтесь со [справочником WIF](https://platform.claude.com/docs/ru/manage-claude/wif-reference), чтобы узнать полный порядок разрешения учётных данных и конфигурацию профилей.
* См. [справочник WIF](https://platform.claude.com/docs/ru/manage-claude/wif-reference#rule-matching-semantics), чтобы выполнять сопоставление по пользовательским утверждениям Okta с помощью CEL-выражений.
