---
title: OktaでWIFを使用する
url: https://platform.claude.com/docs/ja/manage-claude/wif-providers/okta
description: Workload Identity Federationを使用して、OktaサービスアプリケーションのIDをClaude APIにフェデレーションします。
---

Oktaは、OAuth 2.0の`client_credentials`グラントを通じて**サービスアプリケーション**にOIDCアクセストークンを発行することで、ワークロードIDプロバイダーとして機能できます。ワークロードはOktaに対して認証し（通常は`private_key_jwt`を使用するため、共有シークレットは保存されません）、署名付きの「JSON Web Token」（JSONウェブトークン）、すなわちJWTを受け取り、そのJWTをAnthropicと交換して有効期間の短いアクセストークンを取得します。

Okta認可サーバーの発行者（issuer）URLは`https://<your-domain>.okta.com/oauth2/<auth-server-id>`という形式になります。組み込みのデフォルトサーバーを使用する場合、パスは`/oauth2/default`です。

<Note>
  Oktaの**カスタム認可サーバー**（`default`のものを含む）を使用する必要があります。Okta組織認可サーバー（パスに認可サーバーIDを含まない`/oauth2/v1/token`エンドポイント）から直接発行されたトークンは、Oktaがそれらの署名鍵を公開していないため、外部の当事者が検証することはできません。
</Note>

Oktaの設定方法や認証方法は多数ありますが、それらは本ドキュメントの範囲外です。設定および認証メカニズムが、所属する企業のガイダンスとセキュリティプラクティスに従っていることを確認してください。

## 前提条件

* [WIFの概念](https://platform.claude.com/docs/ja/manage-claude/workload-identity-federation#concepts)（サービスアカウント、フェデレーション発行者、フェデレーションルール）を理解していること。
* API Access Managementが有効になっているOkta組織（カスタム認可サーバーに必要）。
* Anthropic組織のClaude Consoleでサービスアカウント、フェデレーション発行者、フェデレーションルールを作成する権限。
* Oktaの`/v1/token`エンドポイントからトークンをリクエストでき、`api.anthropic.com`に到達できるワークロード。

## Oktaを設定する

大まかには、次のことを行う必要があります。

1. Oktaサービスアプリケーションを作成する。
2. デフォルトの認可サーバーを設定する（または新しいカスタム認可サーバーを作成する）。オーディエンス、スコープ、アクセスポリシー、および照合に使用したいカスタムクレームを設定します。

正確なナビゲーションは、Okta組織の設定と管理コンソールのバージョンによって異なります。以下の番号付きの手順では、一般的な経路の1つを説明します。

1. **サービスアプリ統合を作成する。** Okta Admin Consoleで、**API Services**タイプ（OIDC、マシン間）の新しいアプリ統合を作成します。生成された**Client ID**を控えておきます。
2. **クライアント認証を設定する。** キーレス構成の場合は、**Public key / Private key**（`private_key_jwt`）を選択し、ワークロードの公開JWKを登録します。あるいは、環境でクライアントシークレットを安全に保存できる場合は、クライアントシークレットを使用します。以下の例では、アプリケーションのDPoP要件を無効にする必要がある場合があります。本番環境の構成が組織のセキュリティ要件に準拠していることを確認してください。
3. **オーディエンスを設定する。** カスタム認可サーバーで、オーディエンスを`https://api.anthropic.com`に設定し、発行されるアクセストークンがその`aud`クレームを持つようにします。Anthropicは`aud`をこの固定値と照合して検証します。
4. **スコープを付与する。** カスタム認可サーバーで、サービスアプリがリクエストを許可されているスコープが少なくとも1つ存在することを確認します（例：`anthropic.access`）。Oktaは、付与されたスコープを含まない`client_credentials`リクエストを拒否します。
5. **アクセスポリシーを作成する。** カスタム認可サーバーで、手順4で付与したスコープをサービスアプリがリクエストできるようにするルールを少なくとも1つ含むアクセスポリシーを作成します。
6. **（オプション）カスタムクレームを追加する。** クライアントID以外のもので照合したい場合は、認可サーバーの**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/ja/manage-claude/wif-admin-api)に送信する場合でも、以下の値を使用してください。

**フェデレーション発行者：** Oktaカスタム認可サーバーのURLとディスカバリーモードを使用します。AnthropicはOktaの`.well-known/openid-configuration`ディスカバリードキュメントを読み取り、そこで公開されている`jwks_uri`からJWKSを取得します。

```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をIDトークンとしてAnthropic SDKに渡す必要があります。

<CodeGroup>
  ```bash cURL
  # 1. Okta からアクセストークンを取得します（private_key_jwt を使用した client_credentials）。
  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. Okta の JWT を 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",
              # Okta アプリの秘密鍵で署名した RFC 7523 の client_assertion JWT を作成します
              "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",
        // Okta アプリの秘密鍵で署名した RFC 7523 の client_assertion JWT を作成します
        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"},
  		// Okta アプリの秘密鍵で署名した RFC 7523 の client_assertion JWT を作成します
  		"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",
                      // Okta アプリの秘密鍵で署名した RFC 7523 の client_assertion JWT を作成します
                      "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",
              // Okta アプリの秘密鍵で署名した RFC 7523 の client_assertion JWT を作成します
              ["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',
                  // Okta アプリの秘密鍵で署名した RFC 7523 の client_assertion JWT を作成します
                  '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",
      # Okta アプリの秘密鍵で署名した RFC 7523 の client_assertion JWT を作成します
      "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のトークン取得処理は、トークンを無期限にキャッシュするのではなく、呼び出しごとに新しいトークンを返すようにしてください。`ant` CLIは交換のたびに`ANTHROPIC_IDENTITY_TOKEN_FILE`を再読み込みするため、長時間実行されるシェルではタイマーでそのファイルを更新してください。

## セットアップを検証する

交換が成功すると、`sk-ant-oat01-`で始まる`access_token`と、秒単位の`expires_in`値が返されます。交換が不透明な`401` `authentication_error`レスポンス（メッセージ`Authentication failed`）で失敗した場合は、Claude Consoleの[認証履歴ページ](https://platform.claude.com/settings/workload-identity-federation?tab=history)で拒否理由を確認し、[失敗した交換のトラブルシューティング](https://platform.claude.com/docs/ja/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`でそれらを照合します。
* **サービスアプリごとに1つのルールを使用する：** 1つのルールを複数のアプリで共有するのではなく、サービスアプリごとに個別のフェデレーションルールを作成します。

## 次のステップ

* 完全な認証情報の解決順序とプロファイル設定については、[WIFリファレンス](https://platform.claude.com/docs/ja/manage-claude/wif-reference)を確認してください。
* CEL式を使用してカスタムOktaクレームで照合するには、[WIFリファレンス](https://platform.claude.com/docs/ja/manage-claude/wif-reference#rule-matching-semantics)を参照してください。
