---
title: Usare WIF con Microsoft Entra ID
url: https://platform.claude.com/docs/it/manage-claude/wif-providers/azure
description: Federa le identità gestite di Azure e Entra Workload Identity con la Claude API in modo che i tuoi carichi di lavoro Azure possano chiamare Claude senza chiavi API statiche.
---

I carichi di lavoro Azure si autenticano alla Claude API presentando un JSON Web Token (JWT) emesso da Microsoft Entra ID, quindi scambiandolo con un token di accesso Anthropic di breve durata. La configurazione segue la stessa struttura su ogni piattaforma Azure:

1. **Registra l'audience del token:** Crea una app registration nel tuo tenant Microsoft Entra per rappresentare l'audience della Claude API. Ogni carico di lavoro nel tenant richiede token Entra per essa.
2. **Configura l'identità per la tua piattaforma:** Una "managed identity" (identità gestita) su VM, VM Scale Set, App Service, Functions e Container Apps, oppure Entra Workload Identity su AKS.
3. **Configura Anthropic:** Registra l'issuer Entra del tuo tenant, crea un service account e scrivi una regola di federazione che corrisponda ai claim del token.
4. **Scambia a runtime:** Il tuo carico di lavoro scambia il proprio token emesso da Entra presso `POST /v1/oauth/token` con un token di accesso Anthropic `sk-ant-oat01-...` e chiama Claude con esso.

In entrambi i percorsi il token che presenti ad Anthropic contiene l'issuer Entra specifico del tuo tenant e l'object ID dell'identità gestita nei claim `sub` e `oid`; cambia solo il modo in cui il carico di lavoro ottiene quel token. Scegli la sezione relativa a dove viene eseguito il tuo carico di lavoro: [Usare un'identità gestita](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#use-a-managed-identity) per VM, VM Scale Set, App Service, Functions o Container Apps; [Usare Entra Workload Identity su AKS](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#use-entra-workload-identity-on-aks) per AKS.

## Prerequisiti

* Familiarità con i [concetti di WIF](https://platform.claude.com/docs/it/manage-claude/workload-identity-federation#concepts): service account, issuer di federazione e regole di federazione.
* Una sottoscrizione Azure con il permesso di assegnare identità gestite (o di configurare Entra Workload Identity su AKS).
* Il permesso di creare una app registration e un service principal nel tuo tenant Microsoft Entra (l'audience condivisa della Claude API). Entra emette token solo per un'audience che esiste nel tenant, quindi il passaggio [Registrare l'audience del token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#register-the-token-audience) è obbligatorio prima che qualsiasi richiesta di token abbia successo.
* L'ID del tuo tenant Microsoft Entra. Lo trovi nel portale Azure in **Microsoft Entra ID → Overview → Tenant ID**.
* Il permesso di creare service account, issuer di federazione e regole di federazione nella Claude Console per la tua organizzazione Anthropic.

## Registrare l'audience del token

Microsoft Entra ID emette un token solo quando l'audience richiesta esiste nel tuo tenant come app registration con un service principal. Crea una app registration per rappresentare l'audience della Claude API; ogni carico di lavoro nel tenant può richiedere token per essa. Senza questa registrazione, le richieste di token falliscono con un errore "resource not found in tenant" (`AADSTS50001` dagli endpoint dell'identità gestita, `AADSTS500011` dall'endpoint token di Entra).

```bash
# Crea la registrazione dell'app che rappresenta l'audience della Claude API.
APP_ID=$(az ad app create --display-name claude-api-federation --query appId -o tsv)

# Richiedi token di accesso v2.0 e imposta l'URI identificatore api://<APP_ID>.
az ad app update --id "$APP_ID" \
  --identifier-uris "api://$APP_ID" \
  --set api.requestedAccessTokenVersion=2

# Crea il service principal affinché l'audience venga risolta nel tuo tenant.
az ad sp create --id "$APP_ID"
```

<Note>
  Usa il formato di identifier URI `api://<APP_ID>`. Entra limita gli identifier URI `https://` ai domini verificati del tuo tenant, quindi un URI come `https://api.anthropic.com` non può essere registrato nella maggior parte dei tenant; `api://<APP_ID>` è accettato ovunque. Con `requestedAccessTokenVersion: 2`, i token per questa audience sono v2.0, che è ciò che questa guida presuppone. Se riutilizzi una registrazione esistente che emette token v1.0, consulta [Se i tuoi token sono v1.0](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
</Note>

## Usare un'identità gestita

Usa questo percorso quando il tuo carico di lavoro viene eseguito su una VM, un VM Scale Set, App Service, Functions o Container Apps. Il carico di lavoro richiede un JWT emesso da Entra per la propria identità gestita assegnata dall'endpoint token locale della piattaforma, quindi scambia quel JWT con Anthropic.

### Configurare l'identità gestita

<Steps>
  <Step title="Collega un'identità gestita">
    Abilita un'identità gestita assegnata dal sistema o assegnata dall'utente sulla tua risorsa Azure. Nel portale Azure, apri la risorsa, vai su **Identity** e attiva **System assigned** (oppure collega un'identità assegnata dall'utente).

    Dopo che l'identità è stata creata, annota il suo **Object (principal) ID**. Questo GUID appare sia come claim `sub` sia come claim `oid` nel token emesso, e la tua regola di federazione Anthropic effettuerà la corrispondenza su di esso. Puoi trovarlo nella pagina **Identity** della risorsa; per un'identità assegnata dall'utente, è l'**Object (principal) ID** nella pagina **Overview** della risorsa identità gestita. (Un'identità gestita ha solo un service principal in Microsoft Entra ID, non una app registration.)
  </Step>

  <Step title="Trova l'endpoint token della piattaforma">
    La piattaforma espone un endpoint token locale una volta che l'identità è collegata:

    * **VM e VM Scale Set:** IMDS all'indirizzo `http://169.254.169.254/metadata/identity/oauth2/token` con l'header `Metadata: true` e `api-version=2018-02-01`.
    * **App Service, Functions e Container Apps:** L'URL nella variabile d'ambiente `IDENTITY_ENDPOINT` con l'header `X-IDENTITY-HEADER` impostato al valore di `IDENTITY_HEADER`, e `api-version=2019-08-01`. IMDS non è raggiungibile su queste piattaforme.

    Se la risorsa ha più di un'identità gestita assegnata dall'utente, aggiungi `client_id=<IDENTITY_CLIENT_ID>` alla richiesta di token per selezionarne una. Azure raccomanda di specificarlo sempre. Senza di esso, il risultato dipende dal fatto che la risorsa abbia anche un'identità assegnata dal sistema abilitata: se la ha, la richiesta ricade silenziosamente su quell'identità e poi fallisce la corrispondenza `oid` della tua regola di federazione; se non la ha, la richiesta fallisce direttamente non appena viene collegata una seconda identità assegnata dall'utente.
  </Step>

  <Step title="Decodifica un token di esempio">
    Richiedi un token dall'endpoint e decodifica il suo payload per confermare i claim su cui la tua regola di federazione deve effettuare la corrispondenza. (Per il comando di decodifica, consulta [Risolvere i problemi di uno scambio fallito](https://platform.claude.com/docs/it/manage-claude/wif-reference#troubleshoot-a-failed-exchange).) Un token v2.0 per un'identità gestita contiene questi claim:

    ```json
    {
      "iss": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
      "sub": "9f8e7d6c-1a2b-3c4d-5e6f-...",
      "aud": "<APP_ID>",
      "oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
      "tid": "<TENANT_ID>",
      "azp": "<IDENTITY_CLIENT_ID>",
      "ver": "2.0",
      "exp": 1775527120
    }
    ```

    | Claim | Valore                                                                                                                                                                                                         | Effettua la corrispondenza quando                                                                                                                                                                                                                              |
    | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `oid` | L'object ID dell'identità gestita, identico a `sub`                                                                                                                                                            | Vuoi autorizzare una specifica identità gestita. Questo è il comportamento predefinito; la regola in [Configurare Anthropic](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#configure-anthropic) effettua la corrispondenza su di esso. |
    | `azp` | Il client ID dell'identità chiamante                                                                                                                                                                           | Vuoi autorizzare ogni carico di lavoro che condivide una app registration. Per un'identità gestita, `azp` è univoco per quell'identità, quindi è equivalente a `oid`.                                                                                          |
    | `aud` | Il client ID della app registration dell'audience (il GUID `<APP_ID>` da [Registrare l'audience del token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#register-the-token-audience)) | Sempre. Il campo `audience` della regola deve essere esattamente uguale al valore `aud` del token.                                                                                                                                                             |
    | `tid` | L'ID del tuo tenant                                                                                                                                                                                            | Vuoi una difesa in profondità. L'URL dell'issuer vincola già il tenant.                                                                                                                                                                                        |

    Se il claim `ver` del token decodificato è `1.0`, i nomi e i valori dei claim differiscono. Consulta [Se i tuoi token sono v1.0](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0) prima di continuare.
  </Step>
</Steps>

### 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 il riquadro **Microsoft Entra**. La procedura guidata ti accompagna nella registrazione dell'issuer, nella creazione di un service account e nella creazione di una regola di federazione.

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):

**Issuer di federazione:** Scegli **v2.0 (login.microsoftonline.com)** nel selettore **Token issuer** della procedura guidata. (Il selettore ha come valore predefinito v1; quel valore predefinito esiste per i tenant che riutilizzano registrazioni più vecchie che emettono ancora token v1.0.) Entra pubblica un documento di discovery OIDC all'URL dell'issuer per tenant, quindi usa la modalità discovery. Ogni tenant Microsoft Entra che federi necessita del proprio record issuer.

```json
{
  "name": "azure-prod-tenant",
  "issuer_url": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
  "jwks": { "type": "discovery" },
  "max_jwt_lifetime_seconds": 86400
}
```

<Warning>
  I carichi di lavoro con identità gestita richiedono `max_jwt_lifetime_seconds: 86400`. Azure emette token di identità gestita con fino a 24 ore tra `iat` ed `exp` perché memorizza nella cache il token di ogni risorsa per quell'intervallo e non offre alcun modo per forzare un aggiornamento anticipato, e il valore predefinito di 1 ora dell'issuer rifiuta tali token, quindi lo scambio fallisce con la risposta opaca `401` `authentication_error` (messaggio `Authentication failed`). Il riquadro Microsoft Entra della procedura guidata Connect workload crea l'issuer con `max_jwt_lifetime_seconds` impostato su `7500` e non fornisce alcun campo per modificarlo durante la creazione, quindi completa la procedura guidata, poi apri la scheda **Issuers** nella pagina [Workload identity](https://platform.claude.com/settings/workload-identity-federation) della Claude Console, modifica l'issuer e aumenta il valore a `86400`. Puoi anche aggiornare l'issuer tramite l'Admin API.
</Warning>

Una durata accettata più lunga significa che un token Entra trapelato rimane scambiabile per più tempo. Se un token trapela, la leva è disabilitare la regola di federazione; una corrispondenza `oid` stretta limita in primo luogo quali identità possono scambiare un token, come descritto in [Delimitare la regola](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#scope-your-rule).

**Regola di federazione:** Effettua la corrispondenza sull'object ID dell'identità gestita e sull'ID del tuo tenant. Per i token v2.0 che questa guida configura, il valore `audience` è il client ID della app registration dell'audience (il GUID `<APP_ID>` da [Registrare l'audience del token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#register-the-token-audience)). Usa il valore `aud` esatto dal tuo token decodificato.

```json
{
  "name": "azure-inference-worker",
  "issuer_id": "fdis_...",
  "match": {
    "audience": "<APP_ID>",
    "claims": {
      "oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
      "tid": "<TENANT_ID>"
    }
  },
  "target": {
    "type": "service_account",
    "service_account_id": "svac_..."
  },
  "workspace_id": "wrkspc_...",
  "oauth_scope": "workspace:developer",
  "token_lifetime_seconds": 600
}
```

`token_lifetime_seconds` è la durata del token di accesso Anthropic restituito dallo scambio, non del token Entra; l'SDK lo rinnova per te.

### Acquisire e usare il token

In fase di esecuzione il tuo carico di lavoro recupera il suo token Entra, lo scambia su `POST /v1/oauth/token` e usa il bearer token restituito per chiamare Claude. L'SDK di Claude gestisce lo scambio e il ciclo di aggiornamento quando fornisci `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `IdentityTokenConfig`), come mostrato negli esempi seguenti. Tranne che in Java (vedi il commento in quell'esempio), tale opzione accetta un token provider, e l'SDK lo richiama a ogni aggiornamento. La scheda cURL mostra il flusso grezzo.

Gli esempi recuperano il token dell'identità gestita dall'endpoint dei token della piattaforma: IMDS su VM e VM Scale Sets, oppure il servizio `IDENTITY_ENDPOINT` su App Service, Functions e Container Apps. Sostituisci `<APP_ID>` nel valore della risorsa `api://<APP_ID>` con il client ID della registrazione dell'app dell'audience di [Registrare l'audience del token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#register-the-token-audience).

<Tip>
  Se il tuo carico di lavoro usa già la libreria client Azure Identity, ottieni il token Entra da essa (`DefaultAzureCredential` con lo scope `api://<APP_ID>/.default`) invece di chiamare direttamente gli endpoint dei token. Forniscilo a `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `IdentityTokenConfig`) come fanno gli esempi. La libreria seleziona l'endpoint corretto su ogni piattaforma Azure, incluso AKS con Entra Workload Identity.
</Tip>

<CodeGroup>
  ```bash cURL
  # 1. Recupera il token emesso da Entra (identità gestita).
  #    Su una VM o un VM Scale Set, usa IMDS. Con più identità assegnate
  #    dall'utente, aggiungi &client_id=<IDENTITY_CLIENT_ID>.
  ENTRA_TOKEN=$(curl -sS -H "Metadata: true" \
    "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=api://<APP_ID>" \
    | jq -r .access_token)

  #    Su App Service, Functions o Container Apps, usa invece il servizio
  #    token locale (lì IMDS non è raggiungibile):
  # ENTRA_TOKEN=$(curl -sS -H "X-IDENTITY-HEADER: $IDENTITY_HEADER" \
  #   "$IDENTITY_ENDPOINT?api-version=2019-08-01&resource=api://<APP_ID>" \
  #   | jq -r .access_token)

  #    Per AKS con Entra Workload Identity, usa invece lo scambio in due passaggi
  #    descritto nella sezione "Use Entra Workload Identity on AKS".

  # 2. Scambialo con un token di accesso Anthropic.
  RESPONSE=$(curl -sS https://api.anthropic.com/v1/oauth/token \
    -H "content-type: application/json" \
    -d @- <<JSON
  {
    "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
    "assertion": "$ENTRA_TOKEN",
    "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
  )

  ACCESS_TOKEN=$(echo "$RESPONSE" | jq -r .access_token)

  # 3. Chiama l'API di Claude con il token bearer.
  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 from Azure"}]
    }' | jq -r '.content[] | select(.type == "text") | .text'
  ```

  ```python Python
  import os

  import anthropic
  import requests
  from anthropic import WorkloadIdentityCredentials

  # L'URI identificatore della registrazione dell'app audience (vedi Registrare l'audience del token).
  AUDIENCE = "api://<APP_ID>"


  def fetch_entra_token() -> str:
      """Fetch a managed identity token from the platform's token endpoint."""
      # Con più identità assegnate dall'utente, aggiungi client_id=<IDENTITY_CLIENT_ID>
      # ai parametri della richiesta per selezionarne una.
      if endpoint := os.environ.get("IDENTITY_ENDPOINT"):
          # App Service, Functions, Container Apps
          response = requests.get(
              endpoint,
              headers={"X-IDENTITY-HEADER": os.environ["IDENTITY_HEADER"]},
              params={"api-version": "2019-08-01", "resource": AUDIENCE},
              timeout=5,
          )
      else:
          # VM o VM Scale Set: Azure Instance Metadata Service (IMDS)
          response = requests.get(
              "http://169.254.169.254/metadata/identity/oauth2/token",
              headers={"Metadata": "true"},
              params={"api-version": "2018-02-01", "resource": AUDIENCE},
              timeout=5,
          )
      response.raise_for_status()
      return response.json()["access_token"]


  client = anthropic.Anthropic(
      credentials=WorkloadIdentityCredentials(
          identity_token_provider=fetch_entra_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 from Azure"}],
  )
  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";

  // L'URI identificatore della registrazione dell'app audience (vedi Registrare l'audience del token).
  const AUDIENCE = "api://<APP_ID>";

  async function fetchEntraToken(): Promise<string> {
    // App Service, Functions e Container Apps iniettano IDENTITY_ENDPOINT;
    // VM e VM Scale Sets usano IMDS.
    // Con più identità assegnate dall'utente, aggiungi &client_id=<IDENTITY_CLIENT_ID>.
    const identityEndpoint = process.env.IDENTITY_ENDPOINT;
    const url = identityEndpoint
      ? `${identityEndpoint}?api-version=2019-08-01&resource=${AUDIENCE}`
      : `http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=${AUDIENCE}`;
    const headers: Record<string, string> = identityEndpoint
      ? { "X-IDENTITY-HEADER": process.env.IDENTITY_HEADER! }
      : { Metadata: "true" };
    const response = await fetch(url, { headers });
    const body = (await response.json()) as { access_token: string };
    return body.access_token;
  }

  const client = new Anthropic({
    credentials: oidcFederationProvider({
      identityTokenProvider: fetchEntraToken,
      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 from Azure" }]
  });
  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"
  	"os"

  	"github.com/anthropics/anthropic-sdk-go"
  	"github.com/anthropics/anthropic-sdk-go/option"
  )

  // L'URI identificatore della registrazione dell'app audience (vedi Registrare l'audience del token).
  const audience = "api://<APP_ID>"

  // fetchEntraToken recupera un token di identità gestita dall'endpoint dei token
  // della piattaforma: IMDS su VM e VM Scale Sets, oppure il servizio IDENTITY_ENDPOINT
  // su App Service, Functions e Container Apps.
  func fetchEntraToken(ctx context.Context) (string, error) {
  	// Con più identità assegnate dall'utente, aggiungi &client_id=<IDENTITY_CLIENT_ID>.
  	tokenURL := "http://169.254.169.254/metadata/identity/oauth2/token" +
  		"?api-version=2018-02-01&resource=" + audience
  	header, value := "Metadata", "true"
  	if endpoint := os.Getenv("IDENTITY_ENDPOINT"); endpoint != "" {
  		tokenURL = endpoint + "?api-version=2019-08-01&resource=" + audience
  		header, value = "X-IDENTITY-HEADER", os.Getenv("IDENTITY_HEADER")
  	}
  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, tokenURL, nil)
  	if err != nil {
  		return "", err
  	}
  	req.Header.Set(header, value)
  	resp, err := http.DefaultClient.Do(req)
  	if err != nil {
  		return "", fmt.Errorf("call token endpoint: %w", err)
  	}
  	defer resp.Body.Close()
  	var body struct {
  		AccessToken string `json:"access_token"`
  	}
  	if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
  		return "", fmt.Errorf("decode token response: %w", err)
  	}
  	return body.AccessToken, nil
  }

  func main() {
  	client := anthropic.NewClient(
  		option.WithFederationTokenProvider(fetchEntraToken, 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 from Azure")),
  		},
  	})
  	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.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;

  void main() throws Exception {
      HttpClient http = HttpClient.newHttpClient();
      // L'URI identificatore della registrazione dell'app audience (vedi Registrare l'audience del token).
      String audience = "api://<APP_ID>";
      // App Service, Functions e Container Apps iniettano IDENTITY_ENDPOINT;
      // VM e VM Scale Sets usano IMDS.
      // Con più identità assegnate dall'utente, aggiungi &client_id=<IDENTITY_CLIENT_ID>.
      String identityEndpoint = System.getenv("IDENTITY_ENDPOINT");
      HttpRequest tokenRequest = identityEndpoint != null
              ? HttpRequest.newBuilder(URI.create(identityEndpoint + "?api-version=2019-08-01&resource=" + audience))
                      .header("X-IDENTITY-HEADER", System.getenv("IDENTITY_HEADER"))
                      .build()
              : HttpRequest.newBuilder(URI.create("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=" + audience))
                      .header("Metadata", "true")
                      .build();

      // L'SDK Java accetta il token stesso o un percorso di file, non una funzione; con
      // source("value"), path(...) contiene il token. L'SDK invia lo stesso token
      // a ogni aggiornamento del token di accesso Anthropic, il che fallisce una volta
      // scaduto o, se ha un claim jti, già usato. Per un processo di lunga durata,
      // passa source("file") e scrivi un nuovo token nel file prima di
      // ogni aggiornamento.
      var response = http.send(tokenRequest, HttpResponse.BodyHandlers.ofString());
      String entraToken = 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(entraToken)
                                      .build())
                              .build())
                      .build()))
              .build();

      var message = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024)
              .addUserMessage("Hello from Azure")
              .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 EntraTokenProvider(),
  });
  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 from Azure" }],
  });
  foreach (var block in message.Content)
  {
      if (block.Value is TextBlock textBlock)
      {
          Console.WriteLine(textBlock.Text);
      }
  }

  class EntraTokenProvider : IIdentityTokenProvider
  {
      // L'URI identificatore della registrazione dell'app audience (vedi Registrare l'audience del token).
      private const string Audience = "api://<APP_ID>";

      private static readonly HttpClient httpClient = new();

      public async Task<string> GetIdentityTokenAsync(CancellationToken ct = default)
      {
          // App Service, Functions e Container Apps iniettano IDENTITY_ENDPOINT;
          // le VM e i VM Scale Sets usano IMDS.
          // Con più identità assegnate dall'utente, aggiungi &client_id=<IDENTITY_CLIENT_ID>.
          var identityEndpoint = Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT");
          using var request = identityEndpoint is not null
              ? new HttpRequestMessage(HttpMethod.Get,
                  $"{identityEndpoint}?api-version=2019-08-01&resource={Audience}")
              {
                  Headers = { { "X-IDENTITY-HEADER", Environment.GetEnvironmentVariable("IDENTITY_HEADER") } },
              }
              : new HttpRequestMessage(HttpMethod.Get,
                  $"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource={Audience}")
              {
                  Headers = { { "Metadata", "true" } },
              };
          using var response = await httpClient.SendAsync(request, ct);
          response.EnsureSuccessStatusCode();
          using var json = await JsonDocument.ParseAsync(
              await response.Content.ReadAsStreamAsync(ct), default, ct);
          return json.RootElement.GetProperty("access_token").GetString()!;
      }
  }
  ```

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

  // L'URI identificatore della registrazione dell'app audience (vedi Registrare l'audience del token).
  const AUDIENCE = 'api://<APP_ID>';

  class EntraIdentityToken implements IdentityTokenProvider
  {
      public function getIdentityToken(): string
      {
          // App Service, Functions e Container Apps iniettano IDENTITY_ENDPOINT;
          // VM e VM Scale Sets usano IMDS.
          // Con più identità assegnate dall'utente, aggiungi &client_id=<IDENTITY_CLIENT_ID>.
          $identityEndpoint = getenv('IDENTITY_ENDPOINT');
          if ($identityEndpoint !== false) {
              $url = $identityEndpoint . '?api-version=2019-08-01&resource=' . AUDIENCE;
              $header = 'X-IDENTITY-HEADER: ' . getenv('IDENTITY_HEADER');
          } else {
              $url = 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=' . AUDIENCE;
              $header = 'Metadata: true';
          }
          $context = stream_context_create([
              'http' => ['header' => $header . "\r\n"],
          ]);
          $body = json_decode(file_get_contents($url, false, $context), true);
          return $body['access_token'];
      }
  }

  $credentials = new CredentialResult(
      provider: new TokenCache(new WorkloadIdentityCredentials(
          identityProvider: new EntraIdentityToken(),
          federationRuleId: getenv('ANTHROPIC_FEDERATION_RULE_ID'),
          organizationId: getenv('ANTHROPIC_ORGANIZATION_ID'),
          serviceAccountId: getenv('ANTHROPIC_SERVICE_ACCOUNT_ID'),
          workspaceId: getenv('ANTHROPIC_WORKSPACE_ID') ?: null,
      )),
  );
  $client = new Client(credentials: $credentials);

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

  ```ruby Ruby
  require "anthropic"
  require "json"
  require "net/http"

  # L'URI identificatore della registrazione dell'app audience (vedi Registrare l'audience del token).
  AUDIENCE = "api://<APP_ID>"

  def fetch_entra_token
    # App Service, Functions e Container Apps iniettano IDENTITY_ENDPOINT;
    # Le VM e i VM Scale Sets usano IMDS.
    # Con più identità assegnate dall'utente, aggiungi &client_id=<IDENTITY_CLIENT_ID>.
    if (endpoint = ENV["IDENTITY_ENDPOINT"])
      url = "#{endpoint}?api-version=2019-08-01&resource=#{AUDIENCE}"
      headers = {"X-IDENTITY-HEADER" => ENV.fetch("IDENTITY_HEADER")}
    else
      url = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=#{AUDIENCE}"
      headers = {"Metadata" => "true"}
    end
    response = Net::HTTP.get(URI(url), headers)
    JSON.parse(response).fetch("access_token")
  end

  credentials = Anthropic::WorkloadIdentityCredentials.new(
    identity_token_provider: -> { fetch_entra_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"]
  )
  client = Anthropic::Client.new(credentials: credentials)

  message = client.messages.create(
    model: "claude-opus-5-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello from Azure"}]
  )
  puts message.content.find { it.type == :text }.text
  ```

  ```bash CLI
  # Scrivi il token di accesso emesso da Entra in un file leggibile dalla CLI.
  # Esempio per una VM o un VM Scale Set (IMDS). Su App Service, Functions o
  # Container Apps, recupera invece da "$IDENTITY_ENDPOINT?api-version=2019-08-01&resource=api://<APP_ID>"
  # con -H "X-IDENTITY-HEADER: $IDENTITY_HEADER".
  # Con più identità assegnate dall'utente, aggiungi &client_id=<IDENTITY_CLIENT_ID>.
  ANTHROPIC_IDENTITY_TOKEN_FILE=$(mktemp)
  trap 'rm -f "$ANTHROPIC_IDENTITY_TOKEN_FILE"' EXIT
  curl -sS -H "Metadata: true" \
    "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=api://<APP_ID>" \
    | jq -r .access_token > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
  export ANTHROPIC_IDENTITY_TOKEN_FILE

  # ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID,
  # ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID vengono letti dall'ambiente.
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "Hello from Azure"}'
  ```
</CodeGroup>

### Verificare la configurazione

Dalla tua risorsa Azure, esegui lo scambio cURL mostrato in [Acquisire e usare il token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#acquire-and-use-the-token) e conferma che `POST /v1/oauth/token` restituisca un `200` con un `access_token` che inizia con `sk-ant-oat01-` e un valore `expires_in` in secondi. 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, quindi decodifica il token Entra (consulta [Risolvere i problemi di uno scambio fallito](https://platform.claude.com/docs/it/manage-claude/wif-reference#troubleshoot-a-failed-exchange) per il comando) e verifica le cause più comuni lato Azure:

* **Issuer non corrispondente:** L'`issuer_url` registrato deve corrispondere esattamente al claim `iss` del token. Un token v2.0 contiene `https://login.microsoftonline.com/<TENANT_ID>/v2.0`; se il claim `ver` decodificato è `1.0`, consulta [Se i tuoi token sono v1.0](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
* **Durata del token:** I token di identità gestita contengono fino a 24 ore tra `iat` ed `exp`. Se l'issuer ha ancora il `7500` della procedura guidata (o il valore predefinito di 1 ora), aumenta `max_jwt_lifetime_seconds` a `86400` come descritto in [Configurare Anthropic](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#configure-anthropic).
* **Audience non corrispondente:** L'`audience` della regola deve essere esattamente uguale all'`aud` del token: il client ID della app registration dell'audience per i token v2.0 che questa guida configura.
* **Nome del claim non corrispondente:** Una regola che effettua la corrispondenza su un claim che il token non contiene non passa mai. I token v1.0 contengono il client ID in `appid`, non in `azp`; consulta [Se i tuoi token sono v1.0](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).

## Usare Entra Workload Identity su AKS

Usa questo percorso quando il tuo carico di lavoro viene eseguito in un pod AKS. Entra Workload Identity federa un service account Kubernetes con un'identità gestita assegnata dall'utente: Kubernetes proietta un token del service account (firmato dall'issuer OIDC del cluster AKS) nel pod al percorso indicato in `AZURE_FEDERATED_TOKEN_FILE`. Quel token proiettato non è un token emesso da Entra, quindi per rimanere sul percorso mediato da Entra descritto in questa pagina, il carico di lavoro esegue uno scambio in due passaggi: prima riscatta il token proiettato presso `https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token` (grant `client_credentials` federato) per un token di accesso emesso da Entra, poi passa quel token Entra all'SDK Anthropic come identity token.

<Tip>
  I pod AKS possono in alternativa saltare lo scambio Entra e presentare direttamente ad Anthropic il token del service account proiettato da Kubernetes. Quel percorso registra presso Anthropic l'issuer OIDC del tuo cluster AKS invece del tuo tenant Entra. Consulta [Usare WIF con Kubernetes](https://platform.claude.com/docs/it/manage-claude/wif-providers/kubernetes) per quel flusso.
</Tip>

### Configurare Entra Workload Identity

<Steps>
  <Step title="Abilita l'issuer OIDC e workload identity sul tuo cluster">
    L'abilitazione di workload identity installa per te il mutating webhook `azure-workload-identity`; distribuiscilo manualmente solo su cluster non AKS. Acquisisci l'URL dell'issuer OIDC del cluster per la credenziale federata che crei in un passaggio successivo.

    ```bash
    az aks update \
      --resource-group <RESOURCE_GROUP> \
      --name <CLUSTER_NAME> \
      --enable-oidc-issuer \
      --enable-workload-identity

    AKS_OIDC_ISSUER=$(az aks show \
      --resource-group <RESOURCE_GROUP> \
      --name <CLUSTER_NAME> \
      --query oidcIssuerProfile.issuerUrl -o tsv)
    ```
  </Step>

  <Step title="Crea un'identità gestita assegnata dall'utente">
    Acquisisci due valori dall'identità: il **Client ID** va nell'annotazione del service account (e viene iniettato nel pod come `AZURE_CLIENT_ID`), e l'**Object (principal) ID** appare come claim `oid` su cui la tua regola di federazione Anthropic effettua la corrispondenza.

    ```bash
    az identity create \
      --resource-group <RESOURCE_GROUP> \
      --name claude-inference-identity \
      --location <LOCATION>

    # Va nell'annotazione del service account; iniettato nel pod come AZURE_CLIENT_ID.
    IDENTITY_CLIENT_ID=$(az identity show \
      --resource-group <RESOURCE_GROUP> \
      --name claude-inference-identity \
      --query clientId -o tsv)

    # Appare come claim oid a cui corrisponde la tua regola di federazione.
    IDENTITY_OBJECT_ID=$(az identity show \
      --resource-group <RESOURCE_GROUP> \
      --name claude-inference-identity \
      --query principalId -o tsv)
    ```
  </Step>

  <Step title="Crea il service account Kubernetes annotato">
    Il webhook `azure-workload-identity` legge l'annotazione `azure.workload.identity/client-id` per iniettare `AZURE_CLIENT_ID` nel pod, che gli esempi in [Acquisire e usare il token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#acquire-and-use-the-token-2) leggono dall'ambiente.

    ```yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: claude-inference
      namespace: inference
      annotations:
        azure.workload.identity/client-id: <IDENTITY_CLIENT_ID>
    ```
  </Step>

  <Step title="Crea la credenziale federata sull'identità gestita">
    La credenziale federata considera attendibile l'issuer OIDC del tuo cluster per quello specifico service account. Il valore `--audience api://AzureADTokenExchange` è l'audience fissa di Entra per i token del service account Kubernetes in ingresso; non ha relazione con l'audience della Claude API che hai registrato in precedenza.

    ```bash
    az identity federated-credential create \
      --resource-group <RESOURCE_GROUP> \
      --identity-name claude-inference-identity \
      --name claude-inference-aks \
      --issuer "$AKS_OIDC_ISSUER" \
      --subject system:serviceaccount:inference:claude-inference \
      --audience api://AzureADTokenExchange
    ```
  </Step>

  <Step title="Etichetta il pod e imposta il suo service account">
    Il pod deve avere l'etichetta `azure.workload.identity/use: "true"` ed essere eseguito come il service account annotato. Il webhook inietta quindi `AZURE_FEDERATED_TOKEN_FILE`, `AZURE_CLIENT_ID` e `AZURE_TENANT_ID` nel pod. Il file in `AZURE_FEDERATED_TOKEN_FILE` contiene il token del service account proiettato da Kubernetes, firmato dall'issuer OIDC del cluster AKS.

    ```yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: inference-worker
      namespace: inference
      labels:
        azure.workload.identity/use: "true"
    spec:
      serviceAccountName: claude-inference
      containers:
        - name: app
          image: your-registry/inference-worker:latest
    ```
  </Step>

  <Step title="Decodifica un token di esempio">
    Il token che la tua regola di federazione Anthropic vede non è il file proiettato; è il token emesso da Entra restituito dallo scambio `client_credentials`. Dall'interno di un pod etichettato, esegui il passaggio 1 dell'esempio cURL in [Acquisire e usare il token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#acquire-and-use-the-token-2) e decodifica il risultato. Contiene la stessa struttura di claim del percorso con identità gestita:

    ```json
    {
      "iss": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
      "sub": "9f8e7d6c-1a2b-3c4d-5e6f-...",
      "aud": "<APP_ID>",
      "oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
      "tid": "<TENANT_ID>",
      "azp": "<IDENTITY_CLIENT_ID>",
      "ver": "2.0",
      "exp": 1775527120
    }
    ```

    `sub` e `oid` sono l'object ID dell'identità gestita, `aud` è il client ID della app registration dell'audience e `azp` è il client ID dell'identità gestita (il valore di `AZURE_CLIENT_ID`). La durata differisce dal percorso con identità gestita: i token `client_credentials` hanno come valore predefinito una finestra casuale da 60 a 90 minuti tra `iat` ed `exp`, non 24 ore.
  </Step>
</Steps>

### 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 il riquadro **Microsoft Entra**. La procedura guidata ti accompagna nella registrazione dell'issuer, nella creazione di un service account e nella creazione di una regola di federazione.

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):

**Issuer di federazione:** Scegli **v2.0 (login.microsoftonline.com)** nel selettore **Token issuer** della procedura guidata. (Il selettore ha come valore predefinito v1; quel valore predefinito esiste per i tenant che riutilizzano registrazioni più vecchie che emettono ancora token v1.0.) Entra pubblica un documento di discovery OIDC all'URL dell'issuer per tenant, quindi usa la modalità discovery. Ogni tenant Microsoft Entra che federi necessita del proprio record issuer.

```json
{
  "name": "azure-prod-tenant",
  "issuer_url": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
  "jwks": { "type": "discovery" },
  "max_jwt_lifetime_seconds": 7500
}
```

<Warning>
  Il riquadro Microsoft Entra della procedura guidata Connect workload crea l'issuer con `max_jwt_lifetime_seconds` impostato su `7500` (poco più di 2 ore), che copre la durata predefinita da 60 a 90 minuti dei token `client_credentials`. Una policy di durata dei token del tenant o la Continuous Access Evaluation (CAE) possono estendere tale durata. Se nel tuo token decodificato `exp` meno `iat` supera 7500 secondi, modifica l'issuer nella scheda **Issuers** della pagina [Workload identity](https://platform.claude.com/settings/workload-identity-federation) nella Claude Console e aumenta `max_jwt_lifetime_seconds` di conseguenza, altrimenti gli scambi falliscono con la risposta opaca `401` `authentication_error` (messaggio `Authentication failed`). Se il tuo tenant esegue anche carichi di lavoro con identità gestita da [Usare un'identità gestita](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#use-a-managed-identity), usa il valore `86400` di quella sezione, che copre entrambi i percorsi.
</Warning>

Una durata accettata più lunga significa che un token Entra trapelato rimane scambiabile per più tempo. Se un token trapela, la leva è disabilitare la regola di federazione; una corrispondenza `oid` stretta limita in primo luogo quali identità possono scambiare un token, come descritto in [Delimitare la regola](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#scope-your-rule).

**Regola di federazione:** Effettua la corrispondenza sull'object ID dell'identità gestita e sull'ID del tuo tenant. Per i token v2.0 che questa guida configura, il valore `audience` è il client ID della app registration dell'audience (il GUID `<APP_ID>` da [Registrare l'audience del token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#register-the-token-audience)). Usa il valore `aud` esatto dal tuo token decodificato.

```json
{
  "name": "azure-inference-worker",
  "issuer_id": "fdis_...",
  "match": {
    "audience": "<APP_ID>",
    "claims": {
      "oid": "9f8e7d6c-1a2b-3c4d-5e6f-...",
      "tid": "<TENANT_ID>"
    }
  },
  "target": {
    "type": "service_account",
    "service_account_id": "svac_..."
  },
  "workspace_id": "wrkspc_...",
  "oauth_scope": "workspace:developer",
  "token_lifetime_seconds": 600
}
```

`token_lifetime_seconds` è la durata del token di accesso Anthropic restituito dallo scambio, non del token Entra; l'SDK lo rinnova per te.

### Acquisire e usare il token

In fase di esecuzione il pod esegue lo scambio in due passaggi: invia il token proiettato da Kubernetes (il file in `AZURE_FEDERATED_TOKEN_FILE`) all'endpoint dei token di Entra come asserzione `client_credentials` federata, quindi scambia il token di accesso Entra risultante su `POST /v1/oauth/token`. L'SDK di Claude gestisce il secondo scambio e il ciclo di aggiornamento quando fornisci `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `IdentityTokenConfig`), come mostrato negli esempi seguenti. Tranne che in Java (vedi il commento in quell'esempio), tale opzione accetta il tuo recupero da Entra come token provider, e l'SDK lo richiama a ogni aggiornamento. La scheda cURL mostra il flusso grezzo.

Negli esempi compaiono due client ID diversi. `<APP_ID>` è il client ID della registrazione dell'app dell'audience di [Registrare l'audience del token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#register-the-token-audience); lo scope `api://<APP_ID>/.default` chiede a Entra un token destinato a quell'audience. `$AZURE_CLIENT_ID` è il client ID dell'identità gestita, iniettato dal webhook, e identifica il chiamante. Non sostituire l'uno con l'altro.

<Tip>
  Se il tuo carico di lavoro usa già la libreria client Azure Identity, ottieni il token Entra da essa (`DefaultAzureCredential` con lo scope `api://<APP_ID>/.default`) invece di eseguire tu stesso lo scambio in due passaggi. Forniscilo a `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider`; java: `IdentityTokenConfig`) come fanno gli esempi. La libreria legge le stesse variabili d'ambiente `AZURE_FEDERATED_TOKEN_FILE`, `AZURE_CLIENT_ID` e `AZURE_TENANT_ID` e gestisce lo scambio con Entra.
</Tip>

<CodeGroup>
  ```bash cURL
  # 1. Scambia il token proiettato da Kubernetes (in $AZURE_FEDERATED_TOKEN_FILE)
  #    con un JWT emesso da Entra.
  ENTRA_JWT=$(curl -sS "https://login.microsoftonline.com/$AZURE_TENANT_ID/oauth2/v2.0/token" \
    -d grant_type=client_credentials \
    -d "client_id=$AZURE_CLIENT_ID" \
    --data-urlencode "scope=api://<APP_ID>/.default" \
    -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
    --data-urlencode "client_assertion@$AZURE_FEDERATED_TOKEN_FILE" \
    | jq -r .access_token)

  # 2. Scambia il JWT di Entra con un token di accesso 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": "$ENTRA_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. Chiama la Claude API.
  curl -sS 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 from Azure"}]
    }' | jq -r '.content[] | select(.type == "text") | .text'
  ```

  ```python Python
  import os
  from pathlib import Path

  import anthropic
  import requests
  from anthropic import WorkloadIdentityCredentials


  def fetch_entra_token_via_federation() -> str:
      federated_token = Path(os.environ["AZURE_FEDERATED_TOKEN_FILE"]).read_text()
      response = requests.post(
          f"https://login.microsoftonline.com/{os.environ['AZURE_TENANT_ID']}/oauth2/v2.0/token",
          data={
              "client_id": os.environ["AZURE_CLIENT_ID"],
              "grant_type": "client_credentials",
              "scope": "api://<APP_ID>/.default",
              "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
              "client_assertion": federated_token,
          },
          timeout=5,
      )
      response.raise_for_status()
      return response.json()["access_token"]


  client = anthropic.Anthropic(
      credentials=WorkloadIdentityCredentials(
          identity_token_provider=fetch_entra_token_via_federation,
          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 from Azure"}],
  )
  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";
  import { readFile } from "node:fs/promises";

  async function fetchEntraTokenViaFederation(): Promise<string> {
    const federatedToken = await readFile(process.env.AZURE_FEDERATED_TOKEN_FILE!, "utf8");
    const response = await fetch(
      `https://login.microsoftonline.com/${process.env.AZURE_TENANT_ID}/oauth2/v2.0/token`,
      {
        method: "POST",
        headers: { "content-type": "application/x-www-form-urlencoded" },
        body: new URLSearchParams({
          client_id: process.env.AZURE_CLIENT_ID!,
          grant_type: "client_credentials",
          scope: "api://<APP_ID>/.default",
          client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
          client_assertion: federatedToken
        })
      }
    );
    const body = (await response.json()) as { access_token: string };
    return body.access_token;
  }

  const client = new Anthropic({
    credentials: oidcFederationProvider({
      identityTokenProvider: fetchEntraTokenViaFederation,
      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 from Azure" }]
  });
  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 fetchEntraTokenViaFederation(ctx context.Context) (string, error) {
  	federatedToken, err := os.ReadFile(os.Getenv("AZURE_FEDERATED_TOKEN_FILE"))
  	if err != nil {
  		return "", err
  	}
  	form := url.Values{
  		"client_id":             {os.Getenv("AZURE_CLIENT_ID")},
  		"grant_type":            {"client_credentials"},
  		"scope":                 {"api://<APP_ID>/.default"},
  		"client_assertion_type": {"urn:ietf:params:oauth:client-assertion-type:jwt-bearer"},
  		"client_assertion":      {strings.TrimSpace(string(federatedToken))},
  	}
  	tokenURL := "https://login.microsoftonline.com/" + os.Getenv("AZURE_TENANT_ID") + "/oauth2/v2.0/token"
  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, tokenURL, 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(fetchEntraTokenViaFederation), 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 from Azure")),
  		},
  	})
  	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.nio.file.Files;
  import java.nio.file.Path;
  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(
                      "client_id", System.getenv("AZURE_CLIENT_ID"),
                      "grant_type", "client_credentials",
                      "scope", "api://<APP_ID>/.default",
                      "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
                      "client_assertion", Files.readString(Path.of(System.getenv("AZURE_FEDERATED_TOKEN_FILE"))))
              .entrySet().stream()
              .map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), UTF_8))
              .collect(Collectors.joining("&"));
      var request = HttpRequest.newBuilder(URI.create(
                      "https://login.microsoftonline.com/" + System.getenv("AZURE_TENANT_ID") + "/oauth2/v2.0/token"))
              .header("content-type", "application/x-www-form-urlencoded")
              .POST(HttpRequest.BodyPublishers.ofString(form))
              .build();

      // L'SDK Java accetta il token stesso o un percorso di file, non una funzione; con
      // source("value"), path(...) contiene il token. L'SDK invia lo stesso token
      // a ogni aggiornamento del token di accesso Anthropic, il che fallisce una volta
      // scaduto o, se ha un claim jti, già usato. Per un processo di lunga durata,
      // passa source("file") e scrivi un nuovo token nel file prima di
      // ogni aggiornamento.
      var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
      String entraToken = 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(entraToken)
                                      .build())
                              .build())
                      .build()))
              .build();

      var message = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024)
              .addUserMessage("Hello from Azure")
              .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 EntraFederationTokenProvider(),
  });
  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 from Azure" }],
  });
  foreach (var block in message.Content)
  {
      if (block.Value is TextBlock textBlock)
      {
          Console.WriteLine(textBlock.Text);
      }
  }

  class EntraFederationTokenProvider : IIdentityTokenProvider
  {
      private static readonly HttpClient Http = new();

      public async Task<string> GetIdentityTokenAsync(CancellationToken ct = default)
      {
          var federatedToken = await File.ReadAllTextAsync(
              Environment.GetEnvironmentVariable("AZURE_FEDERATED_TOKEN_FILE")!, ct);
          var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");
          var form = new FormUrlEncodedContent(new Dictionary<string, string>
          {
              ["client_id"] = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")!,
              ["grant_type"] = "client_credentials",
              ["scope"] = "api://<APP_ID>/.default",
              ["client_assertion_type"] = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
              ["client_assertion"] = federatedToken,
          });
          var response = await Http.PostAsync(
              $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/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()!;
      }
  }
  ```

  ```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 EntraIdentityTokenViaFederation implements IdentityTokenProvider
  {
      public function getIdentityToken(): string
      {
          $ch = curl_init('https://login.microsoftonline.com/' . getenv('AZURE_TENANT_ID') . '/oauth2/v2.0/token');
          curl_setopt_array($ch, [
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_POSTFIELDS => http_build_query([
                  'client_id' => getenv('AZURE_CLIENT_ID'),
                  'grant_type' => 'client_credentials',
                  'scope' => 'api://<APP_ID>/.default',
                  'client_assertion_type' => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
                  'client_assertion' => file_get_contents(getenv('AZURE_FEDERATED_TOKEN_FILE')),
              ]),
          ]);
          $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 EntraIdentityTokenViaFederation(),
              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 from Azure']],
  );
  $textBlock = array_find($message->content, static fn ($block): bool => $block->type === 'text');
  echo $textBlock->text, PHP_EOL;
  ```

  ```ruby Ruby
  require "anthropic"
  require "json"
  require "net/http"

  def fetch_entra_token_via_federation
    tenant_id = ENV.fetch("AZURE_TENANT_ID")
    federated_token = File.read(ENV.fetch("AZURE_FEDERATED_TOKEN_FILE"))
    response = Net::HTTP.post_form(
      URI("https://login.microsoftonline.com/#{tenant_id}/oauth2/v2.0/token"),
      "client_id" => ENV.fetch("AZURE_CLIENT_ID"),
      "grant_type" => "client_credentials",
      "scope" => "api://<APP_ID>/.default",
      "client_assertion_type" => "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
      "client_assertion" => federated_token
    )
    JSON.parse(response.body).fetch("access_token")
  end

  client = Anthropic::Client.new(
    credentials: Anthropic::WorkloadIdentityCredentials.new(
      identity_token_provider: -> { fetch_entra_token_via_federation },
      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 from Azure"}]
  )
  puts message.content.find { it.type == :text }.text
  ```

  ```bash CLI
  # 1. Scambia il token proiettato da Kubernetes con un token di accesso
  # emesso da Entra e scrivilo in un file temporaneo leggibile dalla CLI.
  ANTHROPIC_IDENTITY_TOKEN_FILE=$(mktemp)
  trap 'rm -f "$ANTHROPIC_IDENTITY_TOKEN_FILE"' EXIT
  curl -sS "https://login.microsoftonline.com/$AZURE_TENANT_ID/oauth2/v2.0/token" \
    -d client_id="$AZURE_CLIENT_ID" \
    -d grant_type=client_credentials \
    --data-urlencode "scope=api://<APP_ID>/.default" \
    -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
    --data-urlencode client_assertion@"$AZURE_FEDERATED_TOKEN_FILE" \
    | jq -r .access_token > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
  export ANTHROPIC_IDENTITY_TOKEN_FILE

  # 2. Chiama la Claude API. ANTHROPIC_FEDERATION_RULE_ID,
  # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID vengono letti
  # dall'ambiente.
  ant messages create \
    --model claude-opus-5-5 \
    --max-tokens 1024 \
    --message '{role: user, content: "Hello from Azure"}'
  ```
</CodeGroup>

### Verificare la configurazione

Dall'interno di un pod etichettato, esegui lo scambio cURL mostrato in [Acquisire e usare il token](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#acquire-and-use-the-token-2) e conferma che `POST /v1/oauth/token` restituisca un `200` con un `access_token` che inizia con `sk-ant-oat01-` e un valore `expires_in` in secondi. 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, quindi decodifica il token emesso da Entra del passaggio 1 (consulta [Risolvere i problemi di uno scambio fallito](https://platform.claude.com/docs/it/manage-claude/wif-reference#troubleshoot-a-failed-exchange) per il comando) e verifica le cause più comuni lato Azure:

* **Issuer non corrispondente:** L'`issuer_url` registrato deve corrispondere esattamente al claim `iss` del token. Un token v2.0 contiene `https://login.microsoftonline.com/<TENANT_ID>/v2.0`; se il claim `ver` decodificato è `1.0`, consulta [Se i tuoi token sono v1.0](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
* **Durata del token:** Se una policy di durata dei token del tenant o la CAE estende il token `client_credentials` oltre 7500 secondi, aumenta il `max_jwt_lifetime_seconds` dell'issuer come descritto in [Configurare Anthropic](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#configure-anthropic-2).
* **Audience non corrispondente:** L'`audience` della regola deve essere esattamente uguale all'`aud` del token: il client ID della app registration dell'audience per i token v2.0 che questa guida configura.
* **Nome del claim non corrispondente:** Una regola che effettua la corrispondenza su un claim che il token non contiene non passa mai. I token v1.0 contengono il client ID in `appid`, non in `azp`; consulta [Se i tuoi token sono v1.0](https://platform.claude.com/docs/it/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).

## Se i tuoi token sono v1.0

Questa guida configura la app registration dell'audience con `api.requestedAccessTokenVersion: 2`, quindi ogni token che mostra è v2.0. Se riutilizzi una registrazione esistente che lascia `requestedAccessTokenVersion` non impostato, Entra emette invece token v1.0. Decodifica un token di esempio e controlla il suo claim `ver`; se è `1.0`, cambiano quattro cose:

* **Issuer:** Il claim `iss` è `https://sts.windows.net/<TENANT_ID>/` invece di `https://login.microsoftonline.com/<TENANT_ID>/v2.0`. Registra l'URL dell'issuer esattamente come lo riporta il claim `iss` del tuo token. I due URL condividono lo stesso JWKS, quindi la modalità discovery funziona per entrambi.
* **Selettore della procedura guidata:** Scegli **v1 (sts.windows.net)** nel selettore **Token issuer** della procedura guidata Connect workload invece di **v2.0 (login.microsoftonline.com)**.
* **Audience:** Il claim `aud` è l'identifier URI che hai passato come `resource` (ad esempio, `api://<APP_ID>`), non il client ID della registrazione. Imposta l'`audience` della regola di federazione al valore `aud` esatto dal tuo token decodificato.
* **Claim del client ID:** Il client ID dell'identità chiamante appare in `appid`, non in `azp`. I due claim non appaiono mai nello stesso token, quindi una regola che effettua la corrispondenza su `azp` non passa mai con un token v1.0.

I claim `oid`, `sub` e `tid` contengono gli stessi valori in entrambe le versioni, quindi il resto di questa guida si applica senza modifiche.

## Delimitare la regola

Una regola di federazione può effettuare la corrispondenza sul subject del token con `subject_prefix` in aggiunta (o in alternativa) alla mappa `claims`; consulta [Semantica di corrispondenza delle regole](https://platform.claude.com/docs/it/manage-claude/wif-reference#rule-matching-semantics) per come i campi si combinano. I valori `sub` di Entra per queste identità sono GUID canonici a lunghezza fissa, quindi un `subject_prefix` contenente l'intero object ID di 36 caratteri corrisponde solo a quel subject; questa è una proprietà del formato del subject di Entra, non di `subject_prefix` in generale.

<Warning>
  Ogni identità nel tuo tenant può richiedere un token per l'audience registrata, quindi `audience` e `tid` da soli non identificano un carico di lavoro specifico. Una regola che omette una corrispondenza su `oid` (o `azp`/`appid`), o che usa un `subject_prefix` con wildcard o GUID parziale, autorizza ogni identità gestita e service principal nel tenant.
</Warning>

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

* **Effettua la corrispondenza su `oid` come valore esatto:** Imposta `claims.oid` all'intero object ID dell'identità gestita. Un `subject_prefix` impostato a quell'intero object ID è equivalente (la procedura guidata della Console imposta entrambi); non usare mai un `subject_prefix` con wildcard o GUID parziale, che corrisponde a più identità di quelle che intendi.
* **Vincola `tid` come difesa in profondità:** L'URL dell'issuer vincola già il tuo tenant, ma aggiungere `claims.tid` protegge dalla deriva della configurazione se il record issuer viene modificato in seguito.
* **Vincola l'audience:** Imposta `audience` al valore `aud` esatto dal tuo token decodificato in modo che i token emessi per altre applicazioni vengano rifiutati.
* **Usa una regola separata per ogni identità gestita:** Crea una regola per ogni identità anziché una regola che ne autorizzi diverse, in modo da poter revocare l'accesso di un singolo carico di lavoro senza influire sugli altri.

## Passaggi successivi

* Esamina il modello di configurazione completo in [Workload Identity Federation](https://platform.claude.com/docs/it/manage-claude/workload-identity-federation).
* Consulta le [guide dei provider](https://platform.claude.com/docs/it/manage-claude/workload-identity-federation#identity-providers) per AWS, Google Cloud, GitHub Actions e Kubernetes.
* Per variabili d'ambiente, file di profilo e precedenza delle credenziali, consulta il [riferimento WIF](https://platform.claude.com/docs/it/manage-claude/wif-reference).
