---
title: WIF mit Okta verwenden
url: https://platform.claude.com/docs/de/manage-claude/wif-providers/okta
description: Föderiere Identitäten von Okta-Service-Anwendungen mit Workload Identity Federation zur Claude API.
---

Okta kann als Workload-Identitätsanbieter fungieren, indem es über den OAuth-2.0-Grant `client_credentials` OIDC-Zugriffstoken an eine **Service-Anwendung** ausstellt. Dein Workload authentifiziert sich bei Okta (typischerweise mit `private_key_jwt`, sodass kein gemeinsames Geheimnis gespeichert wird), erhält ein signiertes „JSON Web Token“, oder JWT, und tauscht dieses JWT bei Anthropic gegen ein kurzlebiges Zugriffstoken ein.

Die Issuer-URL des Okta-Autorisierungsservers hat die Form `https://<your-domain>.okta.com/oauth2/<auth-server-id>`. Wenn du den integrierten Standardserver verwendest, lautet der Pfad `/oauth2/default`.

<Note>
  Du musst einen Okta-**Custom Authorization Server** (benutzerdefinierten Autorisierungsserver) verwenden (einschließlich des `default`-Servers). Token, die direkt vom Okta-Org-Autorisierungsserver ausgestellt werden (dem Endpunkt `/oauth2/v1/token` ohne Autorisierungsserver-ID im Pfad), können von externen Parteien nicht validiert werden, da Okta für sie keine Signaturschlüssel veröffentlicht.
</Note>

Es gibt viele Möglichkeiten, Okta zu konfigurieren und sich bei Okta zu authentifizieren, die außerhalb des Rahmens dieser Dokumentation liegen. Stelle sicher, dass deine Konfigurations- und Authentifizierungsmechanismen den Richtlinien und Sicherheitspraktiken deines Unternehmens entsprechen.

## Voraussetzungen

* Vertrautheit mit den [WIF-Konzepten](https://platform.claude.com/docs/de/manage-claude/workload-identity-federation#concepts): Service-Accounts, Federation-Issuer und Federation-Regeln.
* Eine Okta-Organisation mit aktiviertem API Access Management (erforderlich für benutzerdefinierte Autorisierungsserver).
* Berechtigung zum Erstellen von Service-Accounts, Federation-Issuern und Federation-Regeln in der Claude Console für deine Anthropic-Organisation.
* Ein Workload, der ein Token vom `/v1/token`-Endpunkt von Okta anfordern und `api.anthropic.com` erreichen kann.

## Okta konfigurieren

Im Überblick musst du Folgendes tun:

1. Eine Okta-Service-Anwendung erstellen.
2. Deinen Standard-Autorisierungsserver konfigurieren (oder einen neuen benutzerdefinierten Autorisierungsserver erstellen) – mit einer Audience, einem Scope, einer Zugriffsrichtlinie und allen benutzerdefinierten Claims, auf die du matchen möchtest.

Die genaue Navigation hängt von der Konfiguration deiner Okta-Organisation und der Version der Admin-Konsole ab. Die folgenden nummerierten Schritte führen durch einen gängigen Weg:

1. **Erstelle eine Service-App-Integration.** Erstelle in der Okta Admin Console eine neue App-Integration vom Typ **API Services** (OIDC, Machine-to-Machine). Notiere die generierte **Client ID**.
2. **Konfiguriere die Client-Authentifizierung.** Wähle für ein schlüsselloses Setup **Public key / Private key** (`private_key_jwt`) und registriere den öffentlichen JWK deines Workloads. Alternativ kannst du ein Client-Secret verwenden, wenn deine Umgebung eines sicher speichern kann. Für das folgende Beispiel musst du möglicherweise die DPoP-Anforderung für die Anwendung deaktivieren; stelle sicher, dass dein Produktions-Setup den Sicherheitsanforderungen deiner Organisation entspricht.
3. **Lege die Audience fest.** Setze auf deinem benutzerdefinierten Autorisierungsserver die Audience auf `https://api.anthropic.com`, damit ausgestellte Zugriffstoken diesen `aud`-Claim tragen. Anthropic validiert `aud` gegen diesen festen Wert.
4. **Gewähre einen Scope.** Stelle auf deinem benutzerdefinierten Autorisierungsserver sicher, dass mindestens ein Scope existiert, den die Service-App anfordern darf (zum Beispiel `anthropic.access`). Okta lehnt `client_credentials`-Anfragen ab, die keinen gewährten Scope enthalten.
5. **Erstelle eine Zugriffsrichtlinie.** Erstelle auf deinem benutzerdefinierten Autorisierungsserver eine Zugriffsrichtlinie mit mindestens einer Regel, die deiner Service-App erlaubt, den in Schritt 4 gewährten Scope anzufordern.
6. **(Optional) Füge benutzerdefinierte Claims hinzu.** Wenn du auf etwas anderes als die Client ID matchen möchtest, füge dem Zugriffstoken im Tab **Claims** deines Autorisierungsservers einen Claim hinzu.

Für eine Service-App, die `client_credentials` verwendet, setzt Okta den `sub`-Claim des ausgestellten Zugriffstokens auf die **Client ID** der Anwendung und `iss` auf die Issuer-URL des Autorisierungsservers.

## Anthropic konfigurieren

Gehe in der Claude Console zur Seite [Workload identity](https://platform.claude.com/settings/workload-identity-federation) (`platform.claude.com/settings/workload-identity-federation`), klicke auf **Connect workload** und wähle **Custom OIDC**. Der Assistent führt dich durch die Registrierung des Issuers, das Erstellen eines Service-Accounts und das Erstellen einer Federation-Regel.

Der Assistent erstellt diese Ressourcen für dich. Verwende die folgenden Werte, unabhängig davon, ob du sie im Assistenten eingibst oder an die [Admin API](https://platform.claude.com/docs/de/manage-claude/wif-admin-api) sendest:

**Federation-Issuer:** Verwende die URL deines benutzerdefinierten Okta-Autorisierungsservers und den Discovery-Modus. Anthropic liest das Discovery-Dokument `.well-known/openid-configuration` von Okta und ruft das JWKS von der dort angegebenen `jwks_uri` ab.

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

**Federation-Regel:** Matche auf den Okta-`sub`-Claim, der die Client ID der Service-App ist. Wenn du in Okta benutzerdefinierte Claims definiert hast, kannst du stattdessen mit der `claims`-Map oder einer CEL-`condition` auf diese matchen.

```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
}
```

## Ein Token beziehen und die Claude API aufrufen

Anders als plattformnative Anbieter (AWS, Google Cloud, Kubernetes), die ein Token innerhalb der Laufzeitumgebung des Workloads verfügbar machen (über eine projizierte Datei oder einen lokalen Metadaten-Endpunkt), tut Okta dies nicht. Dein Workload muss den Token-Endpunkt von Okta aufrufen, um ein JWT zu erhalten, und dieses JWT dann als Identitätstoken an das Anthropic SDK übergeben.

<CodeGroup>
  ```bash cURL
  # 1. Fordere ein Access-Token von Okta an (client_credentials mit 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. Tausche das Okta-JWT gegen ein Anthropic-Access-Token.
  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. Rufe die Claude API auf.
  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",
              # Erstelle das RFC 7523 client_assertion-JWT, signiert mit dem Private Key deiner Okta-App
              "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",
        // Erstelle das client_assertion-JWT nach RFC 7523, signiert mit dem Private Key deiner Okta-App
        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"},
  		// Erstelle das client_assertion-JWT nach RFC 7523, signiert mit dem Private Key deiner Okta-App
  		"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",
                      // Erstelle das RFC 7523 client_assertion-JWT, signiert mit dem Private Key deiner Okta-App
                      "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();

      // Das Java SDK nimmt das Token selbst oder einen Dateipfad, keine Funktion; mit
      // source("value") enthält path(...) das Token. Das SDK sendet dasselbe Token
      // bei jeder Aktualisierung des Anthropic-Zugriffstokens, was fehlschlägt, sobald es
      // abgelaufen ist oder, falls es einen jti-Claim hat, bereits verwendet wurde. Für länger laufende
      // Prozesse übergib source("file") und schreibe vor jeder Aktualisierung ein neues Token
      // in die Datei.
      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",
              // Erstelle das client_assertion-JWT nach RFC 7523, signiert mit dem privaten Schlüssel deiner Okta-App
              ["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. Fordere ein Access-Token von Okta an und schreibe es in eine temporäre Datei.
  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. Rufe die Claude API auf. Die CLI liest ANTHROPIC_FEDERATION_RULE_ID,
  # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID, ANTHROPIC_WORKSPACE_ID und
  # ANTHROPIC_IDENTITY_TOKEN_FILE und führt den Austausch durch.
  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',
                  // Erstelle das RFC 7523 client_assertion-JWT, signiert mit dem privaten Schlüssel deiner Okta-App
                  '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",
      # Erstelle das RFC 7523 client_assertion-JWT, signiert mit dem Private Key deiner Okta-App
      "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>

Außer in Java (siehe den Kommentar im Java-Beispiel) übergibt das SDK-Beispiel deinen Okta-Token-Abruf als Token-Provider an `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `IdentityTokenConfig`). Das Claude SDK ruft ihn jedes Mal auf, wenn das Anthropic-Zugriffstoken bald abläuft. Dein Okta-Fetcher sollte daher bei jedem Aufruf ein frisches Token zurückgeben, anstatt eines unbegrenzt zu cachen. Die `ant`-CLI liest `ANTHROPIC_IDENTITY_TOKEN_FILE` bei jedem Austausch erneut ein. Aktualisiere diese Datei bei lang laufenden Shells daher regelmäßig per Timer.

## Das Setup überprüfen

Ein erfolgreicher Austausch gibt ein `access_token` zurück, das mit `sk-ant-oat01-` beginnt, sowie einen `expires_in`-Wert in Sekunden. Wenn der Austausch mit der undurchsichtigen `401`-`authentication_error`-Antwort (Meldung `Authentication failed`) fehlschlägt, prüfe die [Seite mit dem Authentifizierungsverlauf](https://platform.claude.com/settings/workload-identity-federation?tab=history) in der Claude Console auf den Ablehnungsgrund und sieh dir [Einen fehlgeschlagenen Austausch beheben](https://platform.claude.com/docs/de/manage-claude/wif-reference#troubleshoot-a-failed-exchange) an; die häufigste Ursache auf Okta-Seite ist eine nicht übereinstimmende `issuer_url` (sie muss den Pfad `/oauth2/<auth-server-id>` enthalten; der Okta-Org-Autorisierungsserver ist nicht verwendbar).

## Deine Regel eingrenzen

<Warning>
  Mehrere Service-Apps unter demselben Okta-Autorisierungsserver teilen sich denselben Issuer. Eine Regel, die `subject_prefix` weglässt, matcht jede Service-App auf diesem Server, sodass jedes Team, das eine registrieren kann, ein föderiertes Anthropic-Token erhalten könnte.
</Warning>

Beschränke den `match`-Block der Regel auf den engsten Geltungsbereich, der zu deinem Anwendungsfall passt:

* **Fixiere die exakte Client ID:** Setze `subject_prefix` auf die vollständige Client ID der Service-App ohne abschließendes `*`.
* **Fixiere die Audience:** Matche den `audience`-Wert, den du auf dem Autorisierungsserver konfiguriert hast, damit Token, die für eine andere Audience ausgestellt wurden, abgelehnt werden.
* **Matche auf benutzerdefinierte Claims:** Für eine feinere Eingrenzung füge im Tab **Claims** des Autorisierungsservers Claims hinzu und matche sie mit der `claims`-Map der Regel oder einer CEL-`condition`.
* **Verwende eine Regel pro Service-App:** Erstelle für jede Service-App eine eigene Federation-Regel, anstatt eine Regel über mehrere Apps hinweg zu teilen.

## Nächste Schritte

* Lies die [WIF-Referenz](https://platform.claude.com/docs/de/manage-claude/wif-reference) für die vollständige Reihenfolge der Credential-Auflösung und die Profilkonfiguration.
* Sieh dir die [WIF-Referenz](https://platform.claude.com/docs/de/manage-claude/wif-reference#rule-matching-semantics) an, um mit CEL-Ausdrücken auf benutzerdefinierte Okta-Claims zu matchen.
