---
title: Usar WIF con Okta
url: https://platform.claude.com/docs/es/manage-claude/wif-providers/okta
description: Federa identidades de aplicaciones de servicio de Okta a la Claude API con Workload Identity Federation.
---

Okta puede actuar como proveedor de identidad de cargas de trabajo emitiendo tokens de acceso OIDC a una **aplicación de servicio** mediante la concesión `client_credentials` de OAuth 2.0. Tu carga de trabajo se autentica en Okta (normalmente con `private_key_jwt`, de modo que no se almacena ningún secreto compartido), recibe un JSON Web Token (JWT) firmado e intercambia ese JWT con Anthropic por un token de acceso de corta duración.

La URL del emisor del servidor de autorización de Okta tiene la forma `https://<your-domain>.okta.com/oauth2/<auth-server-id>`. Si usas el servidor predeterminado integrado, la ruta es `/oauth2/default`.

<Note>
  Debes usar un **servidor de autorización personalizado** de Okta (incluido el `default`). Los tokens emitidos directamente por el servidor de autorización de la organización de Okta (el endpoint `/oauth2/v1/token` sin ID de servidor de autorización en la ruta) no pueden ser validados por terceros porque Okta no publica las claves de firma correspondientes.
</Note>

Existen muchas formas de configurar Okta y autenticarse en él que están fuera del alcance de esta documentación. Asegúrate de que tus mecanismos de configuración y autenticación sigan las directrices y prácticas de seguridad de tu empresa.

## Requisitos previos

* Familiaridad con los [conceptos de WIF](https://platform.claude.com/docs/es/manage-claude/workload-identity-federation#concepts): cuentas de servicio, emisores de federación y reglas de federación.
* Una organización de Okta con API Access Management habilitado (necesario para los servidores de autorización personalizados).
* Permiso para crear cuentas de servicio, emisores de federación y reglas de federación en la Claude Console para tu organización de Anthropic.
* Una carga de trabajo que pueda solicitar un token al endpoint `/v1/token` de Okta y alcanzar `api.anthropic.com`.

## Configurar Okta

A grandes rasgos, necesitas:

1. Crear una aplicación de servicio de Okta.
2. Configurar tu servidor de autorización predeterminado (o crear un nuevo servidor de autorización personalizado) con una audiencia, un scope, una política de acceso y cualquier claim personalizado con el que quieras hacer coincidencias.

La navegación exacta depende de la configuración de tu organización de Okta y de la versión de la consola de administración. Los siguientes pasos numerados recorren una ruta común:

1. **Crea una integración de aplicación de servicio.** En la Okta Admin Console, crea una nueva integración de aplicación de tipo **API Services** (OIDC, máquina a máquina). Anota el **Client ID** generado.
2. **Configura la autenticación del cliente.** Para una configuración sin claves almacenadas, elige **Public key / Private key** (`private_key_jwt`) y registra la JWK pública de tu carga de trabajo. Como alternativa, usa un secreto de cliente si tu entorno puede almacenarlo de forma segura. Para el siguiente ejemplo, es posible que debas deshabilitar el requisito de DPoP en la aplicación; asegúrate de que tu configuración de producción cumpla con los requisitos de seguridad de tu organización.
3. **Establece la audiencia.** En tu servidor de autorización personalizado, establece la audiencia en `https://api.anthropic.com` para que los tokens de acceso emitidos lleven ese claim `aud`. Anthropic valida `aud` contra este valor fijo.
4. **Concede un scope.** En tu servidor de autorización personalizado, asegúrate de que exista al menos un scope que la aplicación de servicio tenga permitido solicitar (por ejemplo, `anthropic.access`). Okta rechaza las solicitudes `client_credentials` que no incluyan un scope concedido.
5. **Crea una política de acceso.** En tu servidor de autorización personalizado, crea una política de acceso con al menos una regla que permita a tu aplicación de servicio solicitar el scope que concediste en el paso 4.
6. **(Opcional) Agrega claims personalizados.** Si quieres hacer coincidencias con algo distinto del Client ID, agrega un claim al token de acceso en la pestaña **Claims** de tu servidor de autorización.

Para una aplicación de servicio que usa `client_credentials`, Okta establece el claim `sub` del token de acceso emitido en el **Client ID** de la aplicación, y `iss` en la URL del emisor del servidor de autorización.

## Configurar Anthropic

En la Claude Console, ve a la página [Workload identity](https://platform.claude.com/settings/workload-identity-federation) (`platform.claude.com/settings/workload-identity-federation`), haz clic en **Connect workload** y selecciona **Custom OIDC**. El asistente te guía para registrar el emisor, crear una cuenta de servicio y crear una regla de federación.

El asistente crea estos recursos por ti. Usa los siguientes valores, ya sea que los ingreses en el asistente o los envíes a la [Admin API](https://platform.claude.com/docs/es/manage-claude/wif-admin-api):

**Emisor de federación:** Usa la URL de tu servidor de autorización personalizado de Okta y el modo de descubrimiento. Anthropic lee el documento de descubrimiento `.well-known/openid-configuration` de Okta y obtiene el JWKS desde el `jwks_uri` que este anuncia.

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

**Regla de federación:** Haz la coincidencia con el claim `sub` de Okta, que es el Client ID de la aplicación de servicio. Si definiste claims personalizados en Okta, puedes hacer la coincidencia con ellos en su lugar mediante el mapa `claims` o una `condition` CEL.

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

## Obtener un token y llamar a la Claude API

A diferencia de los proveedores nativos de plataforma (AWS, Google Cloud, Kubernetes), que ponen un token a disposición dentro del entorno de ejecución de la carga de trabajo (mediante un archivo proyectado o un endpoint de metadatos local), Okta no lo hace. Tu carga de trabajo debe llamar al endpoint de tokens de Okta para obtener un JWT y luego pasar ese JWT al SDK de Anthropic como token de identidad.

<CodeGroup>
  ```bash cURL
  # 1. Solicita un token de acceso a Okta (client_credentials con 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. Intercambia el JWT de Okta por un token de acceso de 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. Llama a la API de Claude.
  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",
              # Crea el JWT client_assertion de RFC 7523 firmado con la clave privada de tu app de 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",
        // Crea el JWT client_assertion de RFC 7523 firmado con la clave privada de tu app de 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"},
  		// Crea el JWT client_assertion de RFC 7523 firmado con la clave privada de tu app de 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",
                      // Crea el JWT client_assertion de RFC 7523 firmado con la clave privada de tu app de 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();

      // El SDK de Java recibe el token en sí o una ruta de archivo, no una función; con
      // source("value"), path(...) contiene el token. El SDK envía ese mismo token
      // en cada actualización del token de acceso de Anthropic, lo cual falla una vez que
      // ha expirado o, si tiene un claim jti, ya se ha usado. Para un proceso de mayor
      // duración, pasa source("file") y escribe un token nuevo en el archivo antes de
      // cada actualización.
      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",
              // Construye el JWT client_assertion de RFC 7523 firmado con la clave privada de tu app de 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. Solicita un token de acceso a Okta y escríbelo en un archivo temporal.
  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. Llama a la API de Claude. La CLI lee ANTHROPIC_FEDERATION_RULE_ID,
  # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID, ANTHROPIC_WORKSPACE_ID y
  # ANTHROPIC_IDENTITY_TOKEN_FILE, y realiza el intercambio.
  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',
                  // Crea el JWT client_assertion de RFC 7523 firmado con la clave privada de tu app de 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",
      # Crea el JWT client_assertion de RFC 7523 firmado con la clave privada de tu app de 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>

Excepto en Java (consulta el comentario en ese ejemplo), el ejemplo del SDK pasa tu obtención de tokens de Okta a `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `IdentityTokenConfig`) como proveedor de tokens. El SDK de Claude lo llama cada vez que el token de acceso de Anthropic está por caducar, por lo que tu función de obtención de Okta debe devolver un token nuevo en cada llamada en lugar de almacenar uno en caché indefinidamente. La CLI `ant` vuelve a leer `ANTHROPIC_IDENTITY_TOKEN_FILE` en cada intercambio, así que actualiza ese archivo periódicamente con un temporizador en shells de larga duración.

## Verificar la configuración

Un intercambio exitoso devuelve un `access_token` que comienza con `sk-ant-oat01-` y un valor `expires_in` en segundos. Si el intercambio falla con la respuesta opaca `401` `authentication_error` (mensaje `Authentication failed`), revisa la [página del historial de autenticación](https://platform.claude.com/settings/workload-identity-federation?tab=history) en la Claude Console para ver el motivo de la denegación y consulta [Solucionar un intercambio fallido](https://platform.claude.com/docs/es/manage-claude/wif-reference#troubleshoot-a-failed-exchange); la causa más común del lado de Okta es una discrepancia en `issuer_url` (debe incluir la ruta `/oauth2/<auth-server-id>`; el servidor de autorización de la organización de Okta no se puede usar).

## Delimitar el alcance de tu regla

<Warning>
  Varias aplicaciones de servicio bajo el mismo servidor de autorización de Okta comparten el mismo emisor. Una regla que omite `subject_prefix` coincide con todas las aplicaciones de servicio de ese servidor, por lo que cualquier equipo que pueda registrar una podría obtener un token federado de Anthropic.
</Warning>

Restringe el bloque `match` de la regla al alcance más estrecho que se ajuste a tu caso de uso:

* **Fija el Client ID exacto:** Establece `subject_prefix` en el Client ID completo de la aplicación de servicio, sin `*` al final.
* **Fija la audiencia:** Haz coincidir el valor `audience` que configuraste en el servidor de autorización para que se rechacen los tokens emitidos para una audiencia diferente.
* **Haz coincidencias con claims personalizados:** Para un alcance más granular, agrega claims en la pestaña **Claims** del servidor de autorización y hazlos coincidir con el mapa `claims` de la regla o una `condition` CEL.
* **Usa una regla por aplicación de servicio:** Crea una regla de federación independiente para cada aplicación de servicio en lugar de compartir una regla entre aplicaciones.

## Próximos pasos

* Revisa la [referencia de WIF](https://platform.claude.com/docs/es/manage-claude/wif-reference) para conocer el orden completo de resolución de credenciales y la configuración de perfiles.
* Consulta la [referencia de WIF](https://platform.claude.com/docs/es/manage-claude/wif-reference#rule-matching-semantics) para hacer coincidencias con claims personalizados de Okta mediante expresiones CEL.
