---
title: Usare WIF con SPIFFE
url: https://platform.claude.com/docs/it/manage-claude/wif-providers/spiffe
description: Autentica i workload SPIFFE alla Claude API utilizzando JWT-SVID emessi da SPIRE o da qualsiasi altro issuer conforme a SPIFFE.
---

[SPIFFE](https://spiffe.io/) è lo standard CNCF per l'emissione di identità ai workload. [SPIRE](https://spiffe.io/docs/latest/spire-about/) è la sua implementazione di riferimento open-source, e diversi prodotti commerciali emettono anch'essi identità conformi a SPIFFE. Anthropic si federa con qualsiasi implementazione SPIFFE che emetta JWT-SVID compatibili con OIDC. Per un elenco aggiornato delle implementazioni, consulta [Commercial software that implements SPIFFE](https://spiffe.io/docs/latest/spiffe-about/overview/#commercial-software-that-implements-spiffe) sul sito del progetto SPIFFE.

La federazione funziona tramite un documento di discovery OIDC a un URL HTTPS pubblico (modalità `discovery`, soggetta ai [vincoli sugli URL](https://platform.claude.com/docs/it/manage-claude/wif-reference#url-fields)) oppure registrando direttamente il JWKS (modalità `inline`).

La specifica JWT-SVID definisce `sub` come lo SPIFFE ID del workload, e la SPIFFE Workload API richiede che il chiamante fornisca `aud` al momento del fetch, quindi questi claim sono gli stessi in tutte le implementazioni. Anthropic richiede inoltre `iss` e `iat`, nessuno dei quali è imposto dalla specifica JWT-SVID, quindi configura la tua implementazione in modo che popoli entrambi (in SPIRE, `iss` è l'impostazione server `jwt_issuer` e `iat` viene impostato automaticamente). Con questi elementi configurati, le sezioni [Configurare Anthropic](https://platform.claude.com/docs/it/manage-claude/wif-providers/spiffe#configure-anthropic), [Acquisire e usare il token](https://platform.claude.com/docs/it/manage-claude/wif-providers/spiffe#acquire-and-use-the-token) e [Delimitare l'ambito della regola](https://platform.claude.com/docs/it/manage-claude/wif-providers/spiffe#scope-your-rule) di questa guida si applicano a qualsiasi implementazione SPIFFE.

SPIFFE assegna a ogni workload un URI di identità stabile nella forma `spiffe://<trust-domain>/<path>`, e SPIRE emette tale identità come JWT-SVID su richiesta tramite la Workload API. Un JWT-SVID è un normale JWT firmato il cui claim `sub` è lo SPIFFE ID del workload e il cui claim `aud` viene fornito dal workload al momento del fetch.

Il ponte tra un trust domain SPIRE e l'OIDC standard è lo [SPIRE OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md), un helper autonomo che pubblica `/.well-known/openid-configuration` e un endpoint JWKS per le chiavi di firma JWT del trust domain. Con il discovery provider in esecuzione, un JWT-SVID viene validato come qualsiasi altro token OIDC: registra l'URL di discovery come federation issuer (issuer di federazione), scrivi una federation rule (regola di federazione) che corrisponda allo SPIFFE ID del workload e fai in modo che il workload presenti il proprio JWT-SVID all'endpoint di token-exchange di Anthropic.

Gli esempi di questa pagina usano SPIRE e si applicano ovunque sia in esecuzione SPIRE Agent: pod Kubernetes, macchine virtuali e host bare-metal.

<Note>
  Se il tuo cluster Kubernetes non esegue SPIRE e vuoi invece autenticarti con i token di service account proiettati nativi del cluster, consulta [Usare WIF con Kubernetes](https://platform.claude.com/docs/it/manage-claude/wif-providers/kubernetes).
</Note>

## Prerequisiti

* Familiarità con i [concetti di WIF](https://platform.claude.com/docs/it/manage-claude/workload-identity-federation#concepts): service account, federation issuer e federation rule.
* Un deployment SPIFFE con identità dei workload emesse (gli esempi di questa pagina usano SPIRE Server e Agent), e registration entry per i workload che devono chiamare la Claude API.
* Un endpoint di discovery OIDC per il trust domain (in SPIRE, l'[OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md)) in esecuzione con un endpoint HTTPS raggiungibile pubblicamente, oppure il JWKS esportato per la registrazione `inline`.
* Il tuo issuer SPIFFE configurato per impostare il claim `iss` sui JWT-SVID al valore che registrerai come `issuer_url` del federation issuer. Per la modalità `discovery`, questo è l'URL pubblico dell'endpoint di discovery (in SPIRE, l'impostazione server `jwt_issuer`).
* JWT-SVID disponibili per i tuoi workload. WIF accetta solo JWT-SVID, non X.509-SVID.
* Permesso di creare service account, federation issuer e federation rule nella Claude Console per la tua organizzazione Anthropic.

Il valore di audience da richiedere quando si recupera un JWT-SVID è sempre `https://api.anthropic.com`. Usa questo valore in `jwt_audience` di spiffe-helper, nella chiamata `FetchJWTSVID` della Workload API e nel matcher `audience` della federation rule.

## Configurare SPIRE

Le istruzioni di questa sezione sono specifiche per SPIRE. Se usi un issuer SPIFFE diverso, configura il suo endpoint di discovery OIDC e il recupero dei JWT-SVID secondo la sua documentazione, quindi prosegui da [Configurare Anthropic](https://platform.claude.com/docs/it/manage-claude/wif-providers/spiffe#configure-anthropic).

Se esegui già SPIRE con l'OIDC Discovery Provider, la federazione con Anthropic richiede tre cose lato SPIRE: un `jwt_issuer` che corrisponda all'URL di discovery, una registration entry per il workload che chiamerà la Claude API e un modo per quel workload di recuperare un JWT-SVID con l'audience Anthropic. Le sottosezioni seguenti illustrano ciascuna di esse. Gli snippet di configurazione mostrano solo le impostazioni rilevanti per la federazione con Anthropic, non configurazioni complete di deployment SPIRE.

<Tip>
  Stai configurando SPIRE per la prima volta? Esegui il deployment di SPIRE Server e Agent seguendo il [quickstart di SPIRE](https://spiffe.io/docs/latest/try/), quindi aggiungi l'[OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md) come servizio separato accanto a SPIRE Server. La federazione in modalità discovery dipende dal fatto che il provider sia distribuito e raggiungibile pubblicamente. Il provider non fa parte di un'installazione SPIRE predefinita.
</Tip>

### Verificare il JWT issuer

Anthropic valida un JWT-SVID confrontando il suo claim `iss` con un federation issuer registrato e recuperando il JWKS dal documento di discovery di quell'issuer. Due impostazioni SPIRE devono concordare sullo stesso URL: `jwt_issuer` di SPIRE Server (che diventa il claim `iss` in ogni JWT-SVID emesso) e la lista `domains` dell'OIDC Discovery Provider (che determina l'host da cui vengono serviti il documento di discovery e il JWKS). Quell'URL condiviso è ciò che registri presso Anthropic.

Il trust domain e l'issuer URL sono indipendenti. Il trust domain (`spiffe://prod.example.com`) delimita l'ambito del claim `sub`. L'issuer URL (`https://oidc-discovery.prod.example.com`) è dove Anthropic recupera le chiavi di firma. Non è necessario che condividano un hostname.

Conferma che `jwt_issuer` sia impostato nella configurazione di SPIRE Server e punti all'URL pubblico del discovery provider. L'esempio seguente mostra anche una durata predefinita dei JWT-SVID. Il valore predefinito integrato di SPIRE è 5 minuti, abbastanza breve da richiedere una rotazione continua (vedi [Eseguire spiffe-helper](https://platform.claude.com/docs/it/manage-claude/wif-providers/spiffe#run-spiffe-helper)). L'endpoint di token-exchange di Anthropic rifiuta qualsiasi identity token la cui durata superi il massimo configurato per il federation issuer, che è 1 ora per impostazione predefinita (vedi [Regole di validazione](https://platform.claude.com/docs/it/manage-claude/wif-reference#validation-rules)). Questo controllo si applica a ogni implementazione SPIFFE, non solo a SPIRE, quindi mantieni `default_jwt_svid_ttl` (o qualsiasi override per singola entry) pari o inferiore a quel massimo.

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

Nella configurazione dell'OIDC Discovery Provider, lo stesso hostname deve comparire sotto `domains`, e il provider deve poter raggiungere il socket API di SPIRE Server. Il provider serve il documento di discovery e il JWKS tramite HTTPS. Termina TLS con il suo supporto ACME integrato, oppure anteponigli un load balancer che lo faccia.

```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>
  L'esempio usa `server_api`, che connette il discovery provider al socket API privilegiato di SPIRE Server. Il provider accetta anche un blocco `workload_api` (con `socket_path` e `trust_domain`) che ottiene il bundle tramite la Workload API di uno SPIRE Agent. Usalo quando il discovery provider non deve avere accesso alla Server API o è in esecuzione su un nodo che non può raggiungere il Server.
</Note>

### Registrare il workload

Ogni workload che chiama la Claude API necessita di una registration entry SPIRE che mappi i suoi selettori di runtime a uno SPIFFE ID. Se il workload è già registrato, annota il suo SPIFFE ID, che userai nel `subject_prefix` della federation rule. In caso contrario, registralo. Per un pod Kubernetes, i selettori sono tipicamente il namespace e il service account Kubernetes:

```bash CLI
# Sostituisci NODE_UID con l'UID del nodo:
#   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>
  Il `parentID` mostrato è l'agent ID generato automaticamente di un singolo nodo. Per una registrazione a livello di cluster, imposta come parent della entry un [node alias](https://spiffe.io/docs/latest/deploying/registering/#mapping-workloads-to-multiple-nodes) in modo che corrisponda ai workload su ogni nodo, come fa il [quickstart Kubernetes di SPIRE](https://spiffe.io/docs/latest/try/getting-started-k8s/).
</Note>

I workload al di fuori di Kubernetes usano selettori a livello di host come `unix:uid:1000` (`unix:path` è anch'esso disponibile ma richiede `discover_workload_path = true` nella configurazione del workload attestor unix dell'agent). I cluster che eseguono [spire-controller-manager](https://github.com/spiffe/spire-controller-manager) possono dichiarare le entry con la custom resource `ClusterSPIFFEID` invece di chiamare direttamente `spire-server entry create`.

### Eseguire spiffe-helper

[spiffe-helper](https://github.com/spiffe/spiffe-helper) è un'utility sidecar che si connette al socket di SPIRE Agent, recupera un JWT-SVID per una determinata audience, lo scrive in un file e lo recupera nuovamente prima della scadenza. L'helper viene eseguito in modalità daemon per impostazione predefinita. L'esempio seguente imposta `daemon_mode = true` esplicitamente.

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

In Kubernetes, esegui spiffe-helper come container sidecar che condivide un volume `emptyDir` in memoria (`medium: Memory`) con il container della tua applicazione, in modo che lo SVID bearer non finisca mai sul disco del nodo. Monta il socket di SPIRE Agent dall'host nel sidecar, monta il volume condiviso in `/var/run/secrets/anthropic.com` in entrambi i container e imposta `ANTHROPIC_IDENTITY_TOKEN_FILE=/var/run/secrets/anthropic.com/token` sul container dell'applicazione. Su VM e bare metal, esegui spiffe-helper come servizio di sistema accanto al workload e fai puntare entrambi a una directory condivisa.

## Configurare Anthropic

Nella Claude Console, vai alla pagina [Workload identity](https://platform.claude.com/settings/workload-identity-federation) (`platform.claude.com/settings/workload-identity-federation`), fai clic su **Connect workload** e seleziona **Custom OIDC**. La procedura guidata ti accompagna nella registrazione dell'issuer, nella creazione di un service account e nella creazione di una federation rule.

La procedura guidata crea queste risorse per te. Usa i seguenti valori sia che tu li inserisca nella procedura guidata sia che li invii all'[Admin API](https://platform.claude.com/docs/it/manage-claude/wif-admin-api):

**Federation issuer:** Registra l'URL pubblico dell'OIDC Discovery Provider in modalità `discovery`. Anthropic recupera `/.well-known/openid-configuration` da questo URL e segue il `jwks_uri` restituito per ottenere le chiavi di firma del trust domain.

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

Se il discovery provider non è raggiungibile dalla rete internet pubblica, recupera tu stesso il JWKS (`curl https://oidc-discovery.prod.example.com/keys`) e registra l'issuer con `"jwks": {"type": "inline", "keys": [...]}` usando il contenuto dell'array `keys` restituito. In modalità `inline` l'`issuer_url` viene solo confrontato con il claim `iss` del JWT-SVID. Anthropic non tenta mai di raggiungerlo.

<Warning>
  SPIRE ruota le chiavi di firma JWT frequentemente, per impostazione predefinita con la stessa cadenza della CA (`ca_ttl`, 24 ore). Se registri l'issuer con un JWKS inline invece di un URL di discovery, devi aggiornare il JWKS ogni volta che SPIRE esegue la rotazione: aggiungi la nuova chiave prima che i workload inizino a presentarla e **rimuovi le chiavi sostituite** una volta che i token firmati con esse sono scaduti. Le chiavi obsolete lasciate in un JWKS inline rimangono attendibili indefinitamente.
</Warning>

Per automatizzare gli aggiornamenti del JWKS senza esporre un endpoint di discovery pubblico, configura un plugin [BundlePublisher](https://spiffe.io/docs/latest/deploying/spire_server/#built-in-plugins) di SPIRE Server (`aws_s3`, `gcp_cloudstorage` o `k8s_configmap`) con `format = "jwks"` per inviare le chiavi di firma JWT a uno storage esterno a ogni rotazione, quindi aggiorna le chiavi inline dell'issuer tramite l'[Admin API](https://platform.claude.com/docs/it/manage-claude/wif-admin-api#federation-issuers).

**Federation rule:** Fai corrispondere il `sub` del JWT-SVID (lo SPIFFE ID) e l'`aud` che hai configurato spiffe-helper a richiedere. Gli SPIFFE ID sono stringhe URI e `subject_prefix` li confronta come testo opaco, quindi sia un valore esatto sia una corrispondenza per prefisso con `*` finale funzionano con essi. Per pattern più complessi, usa una `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` è la durata dell'access token Anthropic restituito dallo scambio, non del JWT-SVID. L'SDK aggiorna l'access token automaticamente.

Sii specifico quanto il workload consente. Allenta `subject_prefix` a `spiffe://prod.example.com/ns/inference/*` solo se ogni workload registrato sotto quel percorso deve essere mappato allo stesso service account Anthropic. Aggiungi l'ID `fdrl_...` della regola alla variabile d'ambiente `ANTHROPIC_FEDERATION_RULE_ID` del workload.

## Acquisire e usare il token

L'SDK di Claude può leggere il JWT-SVID dal file gestito da spiffe-helper oppure, tranne che in Java, chiamare direttamente la SPIFFE Workload API tramite un token provider. Il percorso basato su file è l'integrazione più semplice e funziona in ogni linguaggio dell'SDK. Il percorso con token provider elimina il sidecar ma richiede un client della SPIFFE Workload API nel linguaggio della tua applicazione.

<Tabs>
  <Tab title="Basato su file con spiffe-helper">
    Con spiffe-helper che scrive un JWT-SVID aggiornato in `/var/run/secrets/anthropic.com/token`, imposta `ANTHROPIC_IDENTITY_TOKEN_FILE` a quel percorso insieme a `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID` e `ANTHROPIC_WORKSPACE_ID`. L'SDK legge il file a ogni token exchange, quindi rileva sempre lo SVID ruotato più di recente, e aggiorna automaticamente l'access token Anthropic prima che scada. Consulta [Variabili d'ambiente](https://platform.claude.com/docs/it/manage-claude/wif-reference#environment-variables) per sapere da dove proviene ciascun valore.

    <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
      # Legge il JWT-SVID che spiffe-helper scrive in
      # ANTHROPIC_IDENTITY_TOKEN_FILE, oltre a 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

      # Legge il JWT-SVID che spiffe-helper scrive in
      # ANTHROPIC_IDENTITY_TOKEN_FILE, oltre a 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";

      // Legge il JWT-SVID che spiffe-helper scrive in
      // ANTHROPIC_IDENTITY_TOKEN_FILE, oltre a 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#
      // Legge il JWT-SVID che spiffe-helper scrive in
      // ANTHROPIC_IDENTITY_TOKEN_FILE, oltre a 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
      // Legge il JWT-SVID che spiffe-helper scrive in
      // ANTHROPIC_IDENTITY_TOKEN_FILE, oltre a 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
      // Legge il JWT-SVID che spiffe-helper scrive in
      // ANTHROPIC_IDENTITY_TOKEN_FILE, oltre a 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;

      // Legge il JWT-SVID che spiffe-helper scrive in
      // ANTHROPIC_IDENTITY_TOKEN_FILE, oltre a 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"

      # Legge il JWT-SVID che spiffe-helper scrive in
      # ANTHROPIC_IDENTITY_TOKEN_FILE, oltre a 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="Token provider tramite la SPIFFE Workload API">
    Tranne che in Java, i workload che integrano direttamente un client SPIFFE Workload API possono saltare spiffe-helper e passare all'SDK un token provider che recupera un JWT-SVID aggiornato dal socket dell'agent. L'SDK invoca il provider prima di ogni token exchange, quindi il workload presenta sempre uno SVID non scaduto. Python ([py-spiffe](https://github.com/HewlettPackard/py-spiffe)) e Go ([go-spiffe](https://github.com/spiffe/go-spiffe)) dispongono di client Workload API maturi.

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

      # Si connette al socket dello SPIRE Agent in 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>
      Per altri linguaggi, recupera il JWT-SVID con il client SPIFFE Workload API del tuo runtime (oppure esegui da shell `spire-agent api fetch jwt`), scrivilo in un file e imposta `ANTHROPIC_IDENTITY_TOKEN_FILE` a quel percorso come nella scheda basata su file.
    </Note>
  </Tab>
</Tabs>

## Verificare la configurazione

Prima di integrare l'SDK, recupera un JWT-SVID direttamente da SPIRE Agent e conferma che i claim corrispondano a quanto si aspetta la tua federation rule. Se usi un'implementazione SPIFFE diversa, recupera un JWT-SVID con la sua CLI o il suo client Workload API e decodifica il payload allo stesso modo.

<Note>
  La Workload API attesta il processo chiamante. Per una registration entry Kubernetes, esegui questo comando all'interno di un pod che soddisfi i selettori della entry e abbia il socket dell'agent montato (ad esempio, usando `kubectl exec`). Su VM e bare metal, eseguilo come l'utente o il processo che corrisponde ai selettori `unix:` della entry. L'esecuzione da una shell host non attestata restituisce `no identity issued`, che è l'errore più comune nella fase di verifica.
</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'
```

Il flag `-output json` restituisce la risposta SVID e la risposta bundle come array JSON di due elementi, quindi `jq -r '.[0].svids[0].svid'` estrae il token puro. Nelle versioni precedenti di SPIRE senza `-output`, il comando stampa invece un blocco etichettato. In tal caso, invia l'output predefinito tramite pipe a `awk '/^[[:space:]]*eyJ/{print $1; exit}'` per estrarre la riga del token. Verifica che `iss` sia l'URL dell'OIDC Discovery Provider che hai registrato, che `sub` sia lo SPIFFE ID del workload e che `aud` contenga `https://api.anthropic.com`. Quindi esegui l'esempio cURL da [Acquisire e usare il token](https://platform.claude.com/docs/it/manage-claude/wif-providers/spiffe#acquire-and-use-the-token). Uno scambio riuscito restituisce un `access_token` che inizia con `sk-ant-oat01-`. Se lo scambio fallisce con la risposta opaca `401` `authentication_error` (messaggio `Authentication failed`), controlla la [pagina della cronologia di autenticazione](https://platform.claude.com/settings/workload-identity-federation?tab=history) nella Claude Console per il motivo del rifiuto e consulta [Risolvere i problemi di uno scambio fallito](https://platform.claude.com/docs/it/manage-claude/wif-reference#troubleshoot-a-failed-exchange). La causa più comune lato SPIRE è una mancata corrispondenza tra il `jwt_issuer` di SPIRE Server e l'URL registrato come federation issuer.

## Delimitare l'ambito della regola

Le convenzioni sui percorsi degli SPIFFE ID sono definite dall'operatore, quindi il matcher `subject_prefix` della federation rule dovrebbe riflettere lo schema di percorsi usato dalle tue registration entry. Schemi comuni includono `spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>` (il valore predefinito emesso dalla risorsa `ClusterSPIFFEID` in spire-controller-manager) e `spiffe://<trust-domain>/host/<hostname>/<service>` per workload su VM e bare-metal.

<Warning>
  Un `subject_prefix` pari a `spiffe://prod.example.com/*` corrisponde a ogni workload nel trust domain. Senza un matcher `audience`, la regola accetta anche JWT-SVID emessi per qualsiasi audience, inclusi quelli che il workload ha richiesto per relying party non correlate.
</Warning>

Vincola il blocco `match` della regola all'ambito più ristretto adatto al tuo caso d'uso:

* **Vincola a un singolo workload:** Imposta `subject_prefix` allo SPIFFE ID completo senza `*` finale.
* **Imposta sempre un'audience:** Richiedi `audience` nella regola e configura spiffe-helper (o la chiamata alla Workload API) con lo stesso valore, in modo che gli SVID emessi per altre relying party vengano rifiutati.
* **Delimita per segmento di percorso:** Usa `spiffe://prod.example.com/ns/inference/*` per autorizzare ogni workload registrato sotto un namespace, e crea una regola e un service account Anthropic separati per ogni namespace invece di ampliare una singola regola.
* **Un issuer per trust domain:** Ogni trust domain SPIRE ha le proprie chiavi di firma e il proprio OIDC Discovery Provider. Registra ciascuno come federation issuer separato e associa le regole all'issuer che possiede gli SPIFFE ID a cui corrispondono.

## Passaggi successivi

<CardGroup cols={2}>
  <Card title="Usare WIF con Okta" icon="lock" href="https://platform.claude.com/docs/it/manage-claude/wif-providers/okta">
    Federa le identità delle service application Okta alla Claude API con Workload Identity Federation.
  </Card>

  <Card title="Workload Identity Federation" icon="cloud" href="https://platform.claude.com/docs/it/manage-claude/workload-identity-federation">
    Autentica i workload alla Claude API con identity token di breve durata dal tuo identity provider invece di chiavi API statiche di lunga durata.
  </Card>

  <Card title="Riferimento WIF" icon="book" href="https://platform.claude.com/docs/it/manage-claude/wif-reference">
    Variabili d'ambiente, regole di validazione, configurazione dei profili e riferimento degli errori per Workload Identity Federation.
  </Card>

  <Card title="Usare WIF con Kubernetes" icon="cube" href="https://platform.claude.com/docs/it/manage-claude/wif-providers/kubernetes">
    Autenticati alla Claude API da cluster Kubernetes autogestiti usando token di service account proiettati.
  </Card>
</CardGroup>
