---
title: Usar WIF com SPIFFE
url: https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/spiffe
description: Autentique workloads SPIFFE na Claude API usando JWT-SVIDs do SPIRE ou de qualquer outro emissor compatível com SPIFFE.
---

[SPIFFE](https://spiffe.io/) é o padrão da CNCF para emissão de identidade para workloads (cargas de trabalho). [SPIRE](https://spiffe.io/docs/latest/spire-about/) é sua implementação de referência de código aberto, e vários produtos comerciais também emitem identidades compatíveis com SPIFFE. A Anthropic federa com qualquer implementação SPIFFE que emita JWT-SVIDs compatíveis com OIDC. Para uma lista atualizada de implementações, consulte [Commercial software that implements SPIFFE](https://spiffe.io/docs/latest/spiffe-about/overview/#commercial-software-that-implements-spiffe) no site do projeto SPIFFE.

A federação funciona por meio de um documento de descoberta OIDC em uma URL HTTPS pública (modo `discovery`, sujeito às [restrições de URL](https://platform.claude.com/docs/pt-BR/manage-claude/wif-reference#url-fields)) ou registrando o JWKS diretamente (modo `inline`).

A especificação JWT-SVID define `sub` como o SPIFFE ID do workload, e a SPIFFE Workload API exige que o chamador forneça `aud` no momento da obtenção, portanto essas claims são as mesmas em todas as implementações. A Anthropic exige adicionalmente `iss` e `iat`, nenhuma das quais a especificação JWT-SVID torna obrigatória, então configure sua implementação para preencher ambas (no SPIRE, `iss` é a configuração de servidor `jwt_issuer` e `iat` é definida automaticamente). Com isso configurado, as seções [Configurar a Anthropic](https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/spiffe#configure-anthropic), [Obter e usar o token](https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/spiffe#acquire-and-use-the-token) e [Delimitar o escopo da sua regra](https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/spiffe#scope-your-rule) deste guia se aplicam a qualquer implementação SPIFFE.

O SPIFFE atribui a cada workload uma URI de identidade estável no formato `spiffe://<trust-domain>/<path>`, e o SPIRE emite essa identidade como um JWT-SVID sob demanda por meio da Workload API. Um JWT-SVID é um JWT assinado comum cuja claim `sub` é o SPIFFE ID do workload e cuja claim `aud` é fornecida pelo workload no momento da obtenção.

A ponte entre um trust domain (domínio de confiança) do SPIRE e o OIDC padrão é o [SPIRE OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md), um auxiliar independente que publica `/.well-known/openid-configuration` e um endpoint JWKS para as chaves de assinatura JWT do trust domain. Com o discovery provider em execução, um JWT-SVID é validado como qualquer outro token OIDC: registre a URL de descoberta como um emissor de federação, escreva uma regra de federação que corresponda ao SPIFFE ID do workload e faça o workload apresentar seu JWT-SVID ao endpoint de troca de tokens da Anthropic.

Os exemplos desta página usam SPIRE e se aplicam a qualquer lugar onde o SPIRE Agent seja executado: pods Kubernetes, máquinas virtuais e hosts bare-metal.

<Note>
  Se o seu cluster Kubernetes não executa SPIRE e você deseja autenticar com os tokens de service account projetados nativos do cluster, consulte [Usar WIF com Kubernetes](https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/kubernetes).
</Note>

## Pré-requisitos

* Familiaridade com os [conceitos de WIF](https://platform.claude.com/docs/pt-BR/manage-claude/workload-identity-federation#concepts): service accounts (contas de serviço), emissores de federação e regras de federação.
* Uma implantação SPIFFE com identidades de workload emitidas (os exemplos desta página usam SPIRE Server e Agent) e entradas de registro para os workloads que precisam chamar a Claude API.
* Um endpoint de descoberta OIDC para o trust domain (no SPIRE, o [OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md)) em execução com um endpoint HTTPS acessível publicamente, ou o JWKS exportado para registro `inline`.
* Seu emissor SPIFFE configurado para definir a claim `iss` nos JWT-SVIDs com o valor que você registrará como `issuer_url` do emissor de federação. Para o modo `discovery`, esta é a URL pública do endpoint de descoberta (no SPIRE, a configuração de servidor `jwt_issuer`).
* JWT-SVIDs disponíveis para seus workloads. O WIF aceita apenas JWT-SVIDs, não X.509-SVIDs.
* Permissão para criar service accounts, emissores de federação e regras de federação no Claude Console para sua organização Anthropic.

O valor de audience (audiência) a ser solicitado ao obter um JWT-SVID é sempre `https://api.anthropic.com`. Use esse valor no `jwt_audience` do spiffe-helper, na chamada `FetchJWTSVID` da Workload API e no matcher `audience` da regra de federação.

## Configurar o SPIRE

As instruções desta seção são específicas do SPIRE. Se você usa um emissor SPIFFE diferente, configure seu endpoint de descoberta OIDC e a obtenção de JWT-SVID de acordo com a documentação dele e, em seguida, continue em [Configurar a Anthropic](https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/spiffe#configure-anthropic).

Se você já executa o SPIRE com o OIDC Discovery Provider, federar com a Anthropic exige três coisas do lado do SPIRE: um `jwt_issuer` que corresponda à URL de descoberta, uma entrada de registro para o workload que chamará a Claude API e uma forma de esse workload obter um JWT-SVID com a audience da Anthropic. As subseções a seguir percorrem cada uma delas. Os trechos de configuração mostram apenas as configurações relevantes para a federação com a Anthropic, não configurações completas de implantação do SPIRE.

<Tip>
  Configurando o SPIRE pela primeira vez? Implante o SPIRE Server e o Agent seguindo o [quickstart do SPIRE](https://spiffe.io/docs/latest/try/) e, em seguida, adicione o [OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md) como um serviço separado ao lado do SPIRE Server. A federação em modo discovery depende de o provider estar implantado e acessível publicamente. O provider não faz parte de uma instalação padrão do SPIRE.
</Tip>

### Verificar o emissor JWT

A Anthropic valida um JWT-SVID comparando sua claim `iss` com um emissor de federação registrado e obtendo o JWKS a partir do documento de descoberta desse emissor. Duas configurações do SPIRE devem concordar na mesma URL: o `jwt_issuer` do SPIRE Server (que se torna a claim `iss` em todo JWT-SVID emitido) e a lista `domains` do OIDC Discovery Provider (que determina o host a partir do qual o documento de descoberta e o JWKS são servidos). Essa URL compartilhada é o que você registra na Anthropic.

O trust domain e a URL do emissor são independentes. O trust domain (`spiffe://prod.example.com`) delimita a claim `sub`. A URL do emissor (`https://oidc-discovery.prod.example.com`) é onde a Anthropic obtém as chaves de assinatura. Eles não precisam compartilhar um hostname.

Confirme que `jwt_issuer` está definido na configuração do SPIRE Server e aponta para a URL pública do discovery provider. O exemplo a seguir também mostra um tempo de vida padrão de JWT-SVID. O padrão interno do SPIRE é de 5 minutos, o que é curto o suficiente para exigir rotação contínua (consulte [Executar o spiffe-helper](https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/spiffe#run-spiffe-helper)). O endpoint de troca de tokens da Anthropic rejeita qualquer token de identidade cujo tempo de vida exceda o máximo configurado do emissor de federação, que é de 1 hora por padrão (consulte [Regras de validação](https://platform.claude.com/docs/pt-BR/manage-claude/wif-reference#validation-rules)). Essa verificação se aplica a toda implementação SPIFFE, não apenas ao SPIRE, portanto mantenha `default_jwt_svid_ttl` (ou qualquer substituição por entrada) igual ou abaixo desse máximo.

```text server.conf
server {
    trust_domain         = "prod.example.com"
    jwt_issuer           = "https://oidc-discovery.prod.example.com"
    default_jwt_svid_ttl = "5m"
    # ...
}
```

Na configuração do OIDC Discovery Provider, o mesmo hostname deve aparecer em `domains`, e o provider deve conseguir alcançar o socket de API do SPIRE Server. O provider serve o documento de descoberta e o JWKS via HTTPS. Termine o TLS com seu suporte ACME integrado ou coloque-o atrás de um load balancer que faça isso.

```text oidc-discovery-provider.conf
domains = ["oidc-discovery.prod.example.com"]

server_api {
    address = "unix:///run/spire/sockets/private/api.sock"
}

acme {
    email        = "platform@example.com"
    tos_accepted = true
}
```

<Note>
  O exemplo usa `server_api`, que conecta o discovery provider ao socket de API privilegiado do SPIRE Server. O provider também aceita um bloco `workload_api` (com `socket_path` e `trust_domain`) que obtém o bundle por meio da Workload API de um SPIRE Agent. Use-o quando o discovery provider não deve ter acesso à Server API ou é executado em um nó que não consegue alcançar o Server.
</Note>

### Registrar o workload

Cada workload que chama a Claude API precisa de uma entrada de registro no SPIRE que mapeie seus seletores de runtime para um SPIFFE ID. Se o workload já estiver registrado, anote seu SPIFFE ID, que você usará no `subject_prefix` da regra de federação. Caso contrário, registre-o. Para um pod Kubernetes, os seletores normalmente são o namespace e a service account do Kubernetes:

```bash CLI
# Substitua NODE_UID pelo UID do nó:
#   kubectl get node <node-name> -o jsonpath='{.metadata.uid}'
spire-server entry create \
    -spiffeID spiffe://prod.example.com/ns/inference/sa/worker \
    -parentID spiffe://prod.example.com/spire/agent/k8s_psat/prod-cluster/NODE_UID \
    -selector k8s:ns:inference \
    -selector k8s:sa:worker
```

<Note>
  O `parentID` mostrado é o agent ID gerado automaticamente de um único nó. Para registro em todo o cluster, associe a entrada a um [node alias](https://spiffe.io/docs/latest/deploying/registering/#mapping-workloads-to-multiple-nodes) para que ela corresponda a workloads em todos os nós, como faz o [quickstart do SPIRE para Kubernetes](https://spiffe.io/docs/latest/try/getting-started-k8s/).
</Note>

Workloads fora do Kubernetes usam seletores de nível de host, como `unix:uid:1000` (`unix:path` também está disponível, mas requer `discover_workload_path = true` na configuração do unix workload attestor do agent). Clusters que executam o [spire-controller-manager](https://github.com/spiffe/spire-controller-manager) podem declarar entradas com o recurso personalizado `ClusterSPIFFEID` em vez de chamar `spire-server entry create` diretamente.

### Executar o spiffe-helper

O [spiffe-helper](https://github.com/spiffe/spiffe-helper) é um utilitário sidecar que se conecta ao socket do SPIRE Agent, obtém um JWT-SVID para uma determinada audience, grava-o em um arquivo e o obtém novamente antes de expirar. O helper é executado em modo daemon por padrão. O exemplo a seguir define `daemon_mode = true` explicitamente.

```text helper.conf
agent_address = "/run/spire/sockets/agent.sock"
# The JWT-SVID file is written under cert_dir
cert_dir      = "/var/run/secrets/anthropic.com"
daemon_mode   = true

jwt_svids = [{
    jwt_audience       = "https://api.anthropic.com"
    jwt_svid_file_name = "token"
}]
```

No Kubernetes, execute o spiffe-helper como um contêiner sidecar que compartilha um volume `emptyDir` em memória (`medium: Memory`) com o contêiner da sua aplicação, para que o SVID bearer nunca seja gravado no disco do nó. Monte o socket do SPIRE Agent do host no sidecar, monte o volume compartilhado em `/var/run/secrets/anthropic.com` em ambos os contêineres e defina `ANTHROPIC_IDENTITY_TOKEN_FILE=/var/run/secrets/anthropic.com/token` no contêiner da aplicação. Em VMs e bare metal, execute o spiffe-helper como um serviço do sistema ao lado do workload e aponte ambos para um diretório compartilhado.

## Configurar a Anthropic

No Claude Console, acesse a página [Workload identity](https://platform.claude.com/settings/workload-identity-federation) (`platform.claude.com/settings/workload-identity-federation`), clique em **Connect workload** e selecione **Custom OIDC**. O assistente orienta você no registro do emissor, na criação de uma service account e na criação de uma regra de federação.

O assistente cria esses recursos para você. Use os seguintes valores, seja inserindo-os no assistente ou enviando-os para a [Admin API](https://platform.claude.com/docs/pt-BR/manage-claude/wif-admin-api):

**Emissor de federação:** Registre a URL pública do OIDC Discovery Provider no modo `discovery`. A Anthropic obtém `/.well-known/openid-configuration` dessa URL e segue o `jwks_uri` retornado para recuperar as chaves de assinatura do trust domain.

```json
{
  "name": "spire-prod",
  "issuer_url": "https://oidc-discovery.prod.example.com",
  "jwks": { "type": "discovery" }
}
```

Se o discovery provider não for acessível pela internet pública, obtenha o JWKS você mesmo (`curl https://oidc-discovery.prod.example.com/keys`) e registre o emissor com `"jwks": {"type": "inline", "keys": [...]}` usando o conteúdo do array `keys` retornado. No modo `inline`, o `issuer_url` é apenas comparado com a claim `iss` do JWT-SVID. A Anthropic nunca tenta acessá-lo.

<Warning>
  O SPIRE rotaciona as chaves de assinatura JWT com frequência, por padrão na mesma cadência da CA (`ca_ttl`, 24 horas). Se você registrar o emissor com um JWKS inline em vez de uma URL de descoberta, deverá atualizar o JWKS toda vez que o SPIRE rotacionar: adicione a nova chave antes que os workloads comecem a apresentá-la e **remova as chaves substituídas** depois que os tokens assinados com elas tiverem expirado. Chaves obsoletas deixadas em um JWKS inline permanecem confiáveis indefinidamente.
</Warning>

Para automatizar as atualizações do JWKS sem expor um endpoint de descoberta público, configure um plugin [BundlePublisher](https://spiffe.io/docs/latest/deploying/spire_server/#built-in-plugins) do SPIRE Server (`aws_s3`, `gcp_cloudstorage` ou `k8s_configmap`) com `format = "jwks"` para enviar as chaves de assinatura JWT para um armazenamento externo a cada rotação e, em seguida, atualize as chaves inline do emissor por meio da [Admin API](https://platform.claude.com/docs/pt-BR/manage-claude/wif-admin-api#federation-issuers).

**Regra de federação:** Faça a correspondência com o `sub` do JWT-SVID (o SPIFFE ID) e o `aud` que você configurou o spiffe-helper para solicitar. SPIFFE IDs são strings URI e `subject_prefix` os compara como texto opaco, portanto tanto um valor exato quanto uma correspondência de prefixo com `*` no final funcionam com eles. Para padrões mais complexos, use uma `condition` CEL.

```json
{
  "name": "spire-inference-worker",
  "issuer_id": "fdis_...",
  "match": {
    "subject_prefix": "spiffe://prod.example.com/ns/inference/sa/worker",
    "audience": "https://api.anthropic.com"
  },
  "target": {
    "type": "service_account",
    "service_account_id": "svac_..."
  },
  "workspace_id": "wrkspc_...",
  "oauth_scope": "workspace:developer",
  "token_lifetime_seconds": 600
}
```

`token_lifetime_seconds` é o tempo de vida do token de acesso da Anthropic que a troca retorna, não do JWT-SVID. O SDK renova o token de acesso automaticamente.

Seja tão específico quanto o workload permitir. Afrouxe `subject_prefix` para `spiffe://prod.example.com/ns/inference/*` somente se todos os workloads registrados sob esse caminho devem ser mapeados para a mesma service account da Anthropic. Adicione o ID `fdrl_...` da regra à variável de ambiente `ANTHROPIC_FEDERATION_RULE_ID` do workload.

## Obter e usar o token

O SDK do Claude pode ler o JWT-SVID do arquivo que o spiffe-helper mantém ou, exceto em Java, chamar a SPIFFE Workload API diretamente por meio de um provedor de token. O caminho por arquivo é a integração mais simples e funciona em todas as linguagens do SDK. O caminho por provedor de token elimina o sidecar, mas exige um cliente da SPIFFE Workload API na linguagem da sua aplicação.

<Tabs>
  <Tab title="Baseado em arquivo com spiffe-helper">
    Com o spiffe-helper gravando um JWT-SVID novo em `/var/run/secrets/anthropic.com/token`, defina `ANTHROPIC_IDENTITY_TOKEN_FILE` com esse caminho, juntamente com `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID` e `ANTHROPIC_WORKSPACE_ID`. O SDK lê o arquivo a cada troca de token, portanto sempre usa o SVID rotacionado mais recentemente, e renova o token de acesso da Anthropic automaticamente antes que ele expire. Consulte [Variáveis de ambiente](https://platform.claude.com/docs/pt-BR/manage-claude/wif-reference#environment-variables) para saber de onde vem cada valor.

    <CodeGroup>
      ```bash cURL
      JWT=$(cat "$ANTHROPIC_IDENTITY_TOKEN_FILE")

      ACCESS_TOKEN=$(curl -sS https://api.anthropic.com/v1/oauth/token \
        -H "content-type: application/json" \
        --data @- <<JSON | jq -r .access_token
      {
        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "assertion": "$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
      )

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

      ```bash CLI
      # Lê o JWT-SVID que o spiffe-helper grava em
      # ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
      # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
      ant messages create \
        --model claude-opus-5-5 \
        --max-tokens 1024 \
        --message '{role: user, content: "Hello, Claude"}'
      ```

      ```python Python
      import anthropic

      # Lê o JWT-SVID que o spiffe-helper grava em
      # ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
      # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
      client = anthropic.Anthropic()

      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";

      // Lê o JWT-SVID que o spiffe-helper grava em
      // ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
      const client = new Anthropic();

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

      ```csharp C#
      // Lê o JWT-SVID que o spiffe-helper grava em
      // ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
      using var client = new AnthropicClient();

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

      ```go Go
      // Lê o JWT-SVID que o spiffe-helper grava em
      // ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
      client := anthropic.NewClient()

      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
      // Lê o JWT-SVID que o spiffe-helper grava em
      // ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

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

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

      ```php PHP
      use Anthropic\Client;

      // Lê o JWT-SVID que o spiffe-helper grava em
      // ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
      $client = new Client();

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

      ```ruby Ruby
      require "anthropic"

      # Lê o JWT-SVID que o spiffe-helper grava em
      # ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
      # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
      client = Anthropic::Client.new

      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>
  </Tab>

  <Tab title="Provedor de token por meio da SPIFFE Workload API">
    Exceto em Java, workloads que vinculam um cliente da SPIFFE Workload API diretamente podem dispensar o spiffe-helper e passar ao SDK um provedor de token que obtém um JWT-SVID novo do socket do agent. O SDK invoca o provedor antes de cada troca de token, portanto o workload sempre apresenta um SVID não expirado. Python ([py-spiffe](https://github.com/HewlettPackard/py-spiffe)) e Go ([go-spiffe](https://github.com/spiffe/go-spiffe)) têm clientes maduros da Workload API.

    <CodeGroup exclude="shell, typescript, java, csharp, php, ruby">
      ```python Python
      import os
      import anthropic
      from anthropic import WorkloadIdentityCredentials
      from spiffe import JwtSource

      AUDIENCE = "https://api.anthropic.com"

      # Conecta-se ao socket do SPIRE Agent em SPIFFE_ENDPOINT_SOCKET.
      jwt_source = JwtSource()


      def fetch_jwt_svid() -> str:
          svid = jwt_source.fetch_svid(audience={AUDIENCE})  # audience is a set of strings
          return svid.token


      client = anthropic.Anthropic(
          credentials=WorkloadIdentityCredentials(
              identity_token_provider=fetch_jwt_svid,
              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"))
      ```

      ```go Go
      import (
      	"context"
      	"fmt"
      	"os"

      	"github.com/anthropics/anthropic-sdk-go"
      	"github.com/anthropics/anthropic-sdk-go/option"
      	"github.com/spiffe/go-spiffe/v2/svid/jwtsvid"
      	"github.com/spiffe/go-spiffe/v2/workloadapi"
      )
      // ...
      	const audience = "https://api.anthropic.com"

      	ctx := context.Background()
      	source, err := workloadapi.NewJWTSource(ctx)
      	if err != nil {
      		panic(err)
      	}
      	defer source.Close()

      	fetchJWTSVID := func(ctx context.Context) (string, error) {
      		svid, err := source.FetchJWTSVID(ctx, jwtsvid.Params{Audience: audience})
      		if err != nil {
      			return "", err
      		}
      		return svid.Marshal(), nil
      	}

      	client := anthropic.NewClient(
      		option.WithFederationTokenProvider(fetchJWTSVID, 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(ctx, 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
      		}
      	}
      ```
    </CodeGroup>

    <Note>
      Para outras linguagens, obtenha o JWT-SVID com o cliente da SPIFFE Workload API do seu runtime (ou execute `spire-agent api fetch jwt` via shell), grave-o em um arquivo e defina `ANTHROPIC_IDENTITY_TOKEN_FILE` com esse caminho, como na aba baseada em arquivo.
    </Note>
  </Tab>
</Tabs>

## Verificar a configuração

Antes de integrar o SDK, obtenha um JWT-SVID diretamente do SPIRE Agent e confirme que as claims correspondem ao que sua regra de federação espera. Se você usa uma implementação SPIFFE diferente, obtenha um JWT-SVID com a CLI ou o cliente da Workload API dela e decodifique o payload da mesma forma.

<Note>
  A Workload API atesta o processo chamador. Para uma entrada de registro do Kubernetes, execute este comando dentro de um pod que satisfaça os seletores da entrada e tenha o socket do agent montado (por exemplo, usando `kubectl exec`). Em VMs e bare metal, execute-o como o usuário ou processo que corresponde aos seletores `unix:` da entrada. Executar a partir de um shell de host não atestado retorna `no identity issued`, que é a falha mais comum na etapa de verificação.
</Note>

```bash CLI
spire-agent api fetch jwt \
    -audience https://api.anthropic.com \
    -socketPath /run/spire/sockets/agent.sock \
    -output json \
  | jq -r '.[0].svids[0].svid' \
  | jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson'
```

A flag `-output json` retorna a resposta do SVID e a resposta do bundle como um array JSON de dois elementos, então `jq -r '.[0].svids[0].svid'` extrai o token puro. Em versões mais antigas do SPIRE sem `-output`, o comando imprime um bloco rotulado. Nesse caso, redirecione a saída padrão por `awk '/^[[:space:]]*eyJ/{print $1; exit}'` para extrair a linha do token. Verifique se `iss` é a URL do OIDC Discovery Provider que você registrou, se `sub` é o SPIFFE ID do workload e se `aud` contém `https://api.anthropic.com`. Em seguida, execute o exemplo cURL de [Obter e usar o token](https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/spiffe#acquire-and-use-the-token). Uma troca bem-sucedida retorna um `access_token` começando com `sk-ant-oat01-`. Se a troca falhar com a resposta opaca `401` `authentication_error` (mensagem `Authentication failed`), verifique a [página de histórico de autenticação](https://platform.claude.com/settings/workload-identity-federation?tab=history) no Claude Console para ver o motivo da negação e consulte [Solucionar problemas de uma troca com falha](https://platform.claude.com/docs/pt-BR/manage-claude/wif-reference#troubleshoot-a-failed-exchange). A causa mais comum do lado do SPIRE é uma incompatibilidade entre o `jwt_issuer` do SPIRE Server e a URL registrada como emissor de federação.

## Delimitar o escopo da sua regra

As convenções de caminho de SPIFFE ID são definidas pelo operador, portanto o matcher `subject_prefix` da regra de federação deve refletir o esquema de caminhos que suas entradas de registro usam. Esquemas comuns incluem `spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>` (o padrão emitido pelo recurso `ClusterSPIFFEID` no spire-controller-manager) e `spiffe://<trust-domain>/host/<hostname>/<service>` para workloads em VMs e bare metal.

<Warning>
  Um `subject_prefix` de `spiffe://prod.example.com/*` corresponde a todos os workloads no trust domain. Sem um matcher `audience`, a regra também aceita JWT-SVIDs emitidos para qualquer audience, incluindo aqueles que o workload solicitou para relying parties não relacionadas.
</Warning>

Restrinja o bloco `match` da regra ao escopo mais estreito que atenda ao seu caso de uso:

* **Fixar em um único workload:** Defina `subject_prefix` com o SPIFFE ID completo, sem `*` no final.
* **Sempre definir uma audience:** Exija `audience` na regra e configure o spiffe-helper (ou a chamada da Workload API) com o mesmo valor, para que SVIDs emitidos para outras relying parties sejam rejeitados.
* **Delimitar por segmento de caminho:** Use `spiffe://prod.example.com/ns/inference/*` para conceder acesso a todos os workloads registrados sob um namespace, e crie uma regra e uma service account da Anthropic separadas por namespace em vez de ampliar uma única regra.
* **Um emissor por trust domain:** Cada trust domain do SPIRE tem suas próprias chaves de assinatura e seu próprio OIDC Discovery Provider. Registre cada um como um emissor de federação separado e vincule as regras ao emissor que possui os SPIFFE IDs aos quais elas correspondem.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Usar WIF com Okta" icon="lock" href="https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/okta">
    Federe identidades de aplicações de serviço do Okta com a Claude API usando Workload Identity Federation.
  </Card>

  <Card title="Workload Identity Federation" icon="cloud" href="https://platform.claude.com/docs/pt-BR/manage-claude/workload-identity-federation">
    Autentique workloads na Claude API com tokens de identidade de curta duração do seu próprio provedor de identidade em vez de chaves de API estáticas de longa duração.
  </Card>

  <Card title="Referência do WIF" icon="book" href="https://platform.claude.com/docs/pt-BR/manage-claude/wif-reference">
    Variáveis de ambiente, regras de validação, configuração de perfil e referência de erros para Workload Identity Federation.
  </Card>

  <Card title="Usar WIF com Kubernetes" icon="cube" href="https://platform.claude.com/docs/pt-BR/manage-claude/wif-providers/kubernetes">
    Autentique-se na Claude API a partir de clusters Kubernetes autogerenciados usando tokens de service account projetados.
  </Card>
</CardGroup>
