---
title: Utiliser WIF avec SPIFFE
url: https://platform.claude.com/docs/fr/manage-claude/wif-providers/spiffe
description: Authentifiez les charges de travail SPIFFE auprès de l'API Claude à l'aide de JWT-SVID provenant de SPIRE ou de tout autre émetteur conforme à SPIFFE.
---

[SPIFFE](https://spiffe.io/) est le standard CNCF pour l'émission d'identités destinées aux charges de travail. [SPIRE](https://spiffe.io/docs/latest/spire-about/) en est l'implémentation de référence open source, et plusieurs produits commerciaux émettent également des identités conformes à SPIFFE. Anthropic se fédère avec toute implémentation SPIFFE qui émet des JWT-SVID compatibles OIDC. Pour une liste à jour des implémentations, consultez [Commercial software that implements SPIFFE](https://spiffe.io/docs/latest/spiffe-about/overview/#commercial-software-that-implements-spiffe) sur le site du projet SPIFFE.

La fédération fonctionne soit via un document de découverte OIDC à une URL HTTPS publique (mode `discovery`, soumis aux [contraintes d'URL](https://platform.claude.com/docs/fr/manage-claude/wif-reference#url-fields)), soit en enregistrant directement le JWKS (mode `inline`).

La spécification JWT-SVID définit `sub` comme l'identifiant SPIFFE de la charge de travail, et la SPIFFE Workload API exige que l'appelant fournisse `aud` au moment de la récupération, de sorte que ces claims sont identiques d'une implémentation à l'autre. Anthropic exige en outre `iss` et `iat`, qu'aucune des deux la spécification JWT-SVID n'impose ; configurez donc votre implémentation pour renseigner les deux (dans SPIRE, `iss` correspond au paramètre serveur `jwt_issuer` et `iat` est défini automatiquement). Une fois ces éléments en place, les sections [Configurer Anthropic](https://platform.claude.com/docs/fr/manage-claude/wif-providers/spiffe#configure-anthropic), [Acquérir et utiliser le jeton](https://platform.claude.com/docs/fr/manage-claude/wif-providers/spiffe#acquire-and-use-the-token) et [Délimiter votre règle](https://platform.claude.com/docs/fr/manage-claude/wif-providers/spiffe#scope-your-rule) de ce guide s'appliquent à toute implémentation SPIFFE.

SPIFFE attribue à chaque charge de travail un URI d'identité stable de la forme `spiffe://<trust-domain>/<path>`, et SPIRE émet cette identité sous forme de JWT-SVID à la demande via la Workload API. Un JWT-SVID est un JWT signé ordinaire dont le claim `sub` est l'identifiant SPIFFE de la charge de travail et dont le claim `aud` est fourni par la charge de travail au moment de la récupération.

Le pont entre un « trust domain » (domaine de confiance) SPIRE et l'OIDC standard est le [SPIRE OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md), un utilitaire autonome qui publie `/.well-known/openid-configuration` et un point de terminaison JWKS pour les clés de signature JWT du domaine de confiance. Lorsque le fournisseur de découverte est en cours d'exécution, un JWT-SVID se valide comme n'importe quel autre jeton OIDC : enregistrez l'URL de découverte en tant qu'émetteur de fédération, rédigez une règle de fédération qui correspond à l'identifiant SPIFFE de la charge de travail, et faites en sorte que la charge de travail présente son JWT-SVID au point de terminaison d'échange de jetons d'Anthropic.

Les exemples de cette page utilisent SPIRE et s'appliquent partout où SPIRE Agent s'exécute : pods Kubernetes, machines virtuelles et hôtes bare-metal.

<Note>
  Si votre cluster Kubernetes n'exécute pas SPIRE et que vous souhaitez plutôt vous authentifier avec les jetons de compte de service projetés natifs du cluster, consultez [Utiliser WIF avec Kubernetes](https://platform.claude.com/docs/fr/manage-claude/wif-providers/kubernetes).
</Note>

## Prérequis

* Une familiarité avec les [concepts WIF](https://platform.claude.com/docs/fr/manage-claude/workload-identity-federation#concepts) : comptes de service, émetteurs de fédération et règles de fédération.
* Un déploiement SPIFFE avec des identités de charge de travail émises (les exemples de cette page utilisent SPIRE Server et Agent), et des entrées d'enregistrement pour les charges de travail qui doivent appeler l'API Claude.
* Un point de terminaison de découverte OIDC pour le domaine de confiance (dans SPIRE, l'[OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md)) fonctionnant avec un point de terminaison HTTPS accessible publiquement, ou le JWKS exporté pour un enregistrement `inline`.
* Votre émetteur SPIFFE configuré pour définir le claim `iss` des JWT-SVID sur la valeur que vous enregistrerez comme `issuer_url` de l'émetteur de fédération. En mode `discovery`, il s'agit de l'URL publique du point de terminaison de découverte (dans SPIRE, le paramètre serveur `jwt_issuer`).
* Des JWT-SVID disponibles pour vos charges de travail. WIF accepte uniquement les JWT-SVID, pas les X.509-SVID.
* L'autorisation de créer des comptes de service, des émetteurs de fédération et des règles de fédération dans la Claude Console pour votre organisation Anthropic.

La valeur d'audience à demander lors de la récupération d'un JWT-SVID est toujours `https://api.anthropic.com`. Utilisez cette valeur dans le `jwt_audience` de spiffe-helper, dans l'appel `FetchJWTSVID` de la Workload API et dans le matcher `audience` de la règle de fédération.

## Configurer SPIRE

Les instructions de cette section sont spécifiques à SPIRE. Si vous utilisez un autre émetteur SPIFFE, configurez son point de terminaison de découverte OIDC et la récupération des JWT-SVID conformément à sa propre documentation, puis poursuivez à la section [Configurer Anthropic](https://platform.claude.com/docs/fr/manage-claude/wif-providers/spiffe#configure-anthropic).

Si vous exécutez déjà SPIRE avec l'OIDC Discovery Provider, la fédération avec Anthropic nécessite trois éléments côté SPIRE : un `jwt_issuer` qui correspond à l'URL de découverte, une entrée d'enregistrement pour la charge de travail qui appellera l'API Claude, et un moyen pour cette charge de travail de récupérer un JWT-SVID avec l'audience Anthropic. Les sous-sections suivantes détaillent chacun de ces éléments. Les extraits de code de configuration ne montrent que les paramètres pertinents pour la fédération avec Anthropic, et non des configurations de déploiement SPIRE complètes.

<Tip>
  Vous configurez SPIRE pour la première fois ? Déployez SPIRE Server et Agent en suivant le [guide de démarrage rapide SPIRE](https://spiffe.io/docs/latest/try/), puis ajoutez l'[OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md) en tant que service distinct aux côtés de SPIRE Server. La fédération en mode découverte dépend du déploiement du fournisseur et de son accessibilité publique. Le fournisseur ne fait pas partie d'une installation SPIRE par défaut.
</Tip>

### Vérifier l'émetteur JWT

Anthropic valide un JWT-SVID en comparant son claim `iss` à un émetteur de fédération enregistré et en récupérant le JWKS à partir du document de découverte de cet émetteur. Deux paramètres SPIRE doivent s'accorder sur la même URL : le `jwt_issuer` de SPIRE Server (qui devient le claim `iss` de chaque JWT-SVID émis) et la liste `domains` de l'OIDC Discovery Provider (qui détermine l'hôte depuis lequel le document de découverte et le JWKS sont servis). Cette URL partagée est celle que vous enregistrez auprès d'Anthropic.

Le domaine de confiance et l'URL de l'émetteur sont indépendants. Le domaine de confiance (`spiffe://prod.example.com`) délimite le claim `sub`. L'URL de l'émetteur (`https://oidc-discovery.prod.example.com`) est l'endroit où Anthropic récupère les clés de signature. Ils n'ont pas besoin de partager un nom d'hôte.

Vérifiez que `jwt_issuer` est défini dans la configuration de SPIRE Server et pointe vers l'URL publique du fournisseur de découverte. L'exemple suivant montre également une durée de vie par défaut des JWT-SVID. La valeur par défaut intégrée de SPIRE est de 5 minutes, ce qui est suffisamment court pour qu'une rotation continue soit nécessaire (voir [Exécuter spiffe-helper](https://platform.claude.com/docs/fr/manage-claude/wif-providers/spiffe#run-spiffe-helper)). Le point de terminaison d'échange de jetons d'Anthropic rejette tout jeton d'identité dont la durée de vie dépasse le maximum configuré pour l'émetteur de fédération, qui est de 1 heure par défaut (voir [Règles de validation](https://platform.claude.com/docs/fr/manage-claude/wif-reference#validation-rules)). Cette vérification s'applique à toute implémentation SPIFFE, pas seulement à SPIRE ; maintenez donc `default_jwt_svid_ttl` (ou toute surcharge par entrée) à une valeur inférieure ou égale à ce maximum.

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

Dans la configuration de l'OIDC Discovery Provider, le même nom d'hôte doit apparaître sous `domains`, et le fournisseur doit pouvoir atteindre le socket API de SPIRE Server. Le fournisseur sert le document de découverte et le JWKS via HTTPS. Terminez TLS avec sa prise en charge ACME intégrée, ou placez-le derrière un équilibreur de charge qui s'en charge.

```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'exemple utilise `server_api`, qui connecte le fournisseur de découverte au socket API privilégié de SPIRE Server. Le fournisseur accepte également un bloc `workload_api` (avec `socket_path` et `trust_domain`) qui obtient le bundle via la Workload API d'un SPIRE Agent à la place. Utilisez-le lorsque le fournisseur de découverte ne doit pas avoir accès à l'API Server ou s'exécute sur un nœud qui ne peut pas atteindre le Server.
</Note>

### Enregistrer la charge de travail

Chaque charge de travail qui appelle l'API Claude a besoin d'une entrée d'enregistrement SPIRE qui associe ses sélecteurs d'exécution à un identifiant SPIFFE. Si la charge de travail est déjà enregistrée, notez son identifiant SPIFFE, que vous utiliserez dans le `subject_prefix` de la règle de fédération. Sinon, enregistrez-la. Pour un pod Kubernetes, les sélecteurs sont généralement le namespace et le compte de service Kubernetes :

```bash CLI
# Remplacez NODE_UID par l'UID du nœud :
#   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>
  Le `parentID` affiché est l'identifiant d'agent généré automatiquement pour un seul nœud. Pour un enregistrement à l'échelle du cluster, rattachez l'entrée à un [alias de nœud](https://spiffe.io/docs/latest/deploying/registering/#mapping-workloads-to-multiple-nodes) afin qu'elle corresponde aux charges de travail sur chaque nœud, comme le fait le [guide de démarrage rapide SPIRE pour Kubernetes](https://spiffe.io/docs/latest/try/getting-started-k8s/).
</Note>

Les charges de travail hors Kubernetes utilisent des sélecteurs au niveau de l'hôte tels que `unix:uid:1000` (`unix:path` est également disponible mais nécessite `discover_workload_path = true` dans la configuration de l'attestateur de charge de travail unix de l'agent). Les clusters exécutant [spire-controller-manager](https://github.com/spiffe/spire-controller-manager) peuvent déclarer des entrées avec la ressource personnalisée `ClusterSPIFFEID` au lieu d'appeler directement `spire-server entry create`.

### Exécuter spiffe-helper

[spiffe-helper](https://github.com/spiffe/spiffe-helper) est un utilitaire sidecar qui se connecte au socket de SPIRE Agent, récupère un JWT-SVID pour une audience donnée, l'écrit dans un fichier et le récupère à nouveau avant son expiration. L'utilitaire s'exécute en mode démon par défaut. L'exemple suivant définit explicitement `daemon_mode = true`.

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

Dans Kubernetes, exécutez spiffe-helper en tant que conteneur sidecar partageant un volume `emptyDir` en mémoire (`medium: Memory`) avec votre conteneur applicatif, afin que le SVID porteur n'atterrisse jamais sur le disque du nœud. Montez le socket de SPIRE Agent depuis l'hôte dans le sidecar, montez le volume partagé sur `/var/run/secrets/anthropic.com` dans les deux conteneurs, et définissez `ANTHROPIC_IDENTITY_TOKEN_FILE=/var/run/secrets/anthropic.com/token` sur le conteneur applicatif. Sur les VM et le bare metal, exécutez spiffe-helper en tant que service système aux côtés de la charge de travail et faites pointer les deux vers un répertoire partagé.

## Configurer Anthropic

Dans la Claude Console, accédez à la page [Workload identity](https://platform.claude.com/settings/workload-identity-federation) (`platform.claude.com/settings/workload-identity-federation`), cliquez sur **Connect workload**, puis sélectionnez **Custom OIDC**. L'assistant vous guide dans l'enregistrement de l'émetteur, la création d'un compte de service et la création d'une règle de fédération.

L'assistant crée ces ressources pour vous. Utilisez les valeurs suivantes, que vous les saisissiez dans l'assistant ou que vous les envoyiez à l'[Admin API](https://platform.claude.com/docs/fr/manage-claude/wif-admin-api) :

**Émetteur de fédération :** enregistrez l'URL publique de l'OIDC Discovery Provider en mode `discovery`. Anthropic récupère `/.well-known/openid-configuration` à partir de cette URL et suit le `jwks_uri` renvoyé pour obtenir les clés de signature du domaine de confiance.

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

Si le fournisseur de découverte n'est pas accessible depuis l'internet public, récupérez le JWKS vous-même (`curl https://oidc-discovery.prod.example.com/keys`) et enregistrez l'émetteur avec `"jwks": {"type": "inline", "keys": [...]}` en utilisant le contenu du tableau `keys` renvoyé. En mode `inline`, l'`issuer_url` est uniquement comparée au claim `iss` du JWT-SVID. Anthropic ne tente jamais de l'atteindre.

<Warning>
  SPIRE effectue fréquemment la rotation des clés de signature JWT, par défaut à la même cadence que la CA (`ca_ttl`, 24 heures). Si vous enregistrez l'émetteur avec un JWKS inline au lieu d'une URL de découverte, vous devez mettre à jour le JWKS à chaque rotation de SPIRE : ajoutez la nouvelle clé avant que les charges de travail ne commencent à la présenter, et **supprimez les clés remplacées** une fois que les jetons signés avec elles ont expiré. Les clés obsolètes laissées dans un JWKS inline restent approuvées indéfiniment.
</Warning>

Pour automatiser les mises à jour du JWKS sans exposer de point de terminaison de découverte public, configurez un plugin [BundlePublisher](https://spiffe.io/docs/latest/deploying/spire_server/#built-in-plugins) de SPIRE Server (`aws_s3`, `gcp_cloudstorage` ou `k8s_configmap`) avec `format = "jwks"` pour pousser les clés de signature JWT vers un stockage externe à chaque rotation, puis mettez à jour les clés inline de l'émetteur via l'[API Admin](https://platform.claude.com/docs/fr/manage-claude/wif-admin-api#federation-issuers).

**Règle de fédération :** faites correspondre le `sub` du JWT-SVID (l'identifiant SPIFFE) et l'`aud` que vous avez configuré spiffe-helper à demander. Les identifiants SPIFFE sont des chaînes URI et `subject_prefix` les compare en tant que texte opaque, de sorte qu'une valeur exacte ou une correspondance de préfixe avec un `*` final fonctionnent toutes deux. Pour des motifs plus complexes, utilisez une `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` est la durée de vie du jeton d'accès Anthropic renvoyé par l'échange, et non celle du JWT-SVID. Le SDK actualise automatiquement le jeton d'accès.

Soyez aussi précis que la charge de travail le permet. N'élargissez `subject_prefix` à `spiffe://prod.example.com/ns/inference/*` que si chaque charge de travail enregistrée sous ce chemin doit correspondre au même compte de service Anthropic. Ajoutez l'identifiant `fdrl_...` de la règle à la variable d'environnement `ANTHROPIC_FEDERATION_RULE_ID` de la charge de travail.

## Acquérir et utiliser le jeton

Le SDK Claude peut lire le JWT-SVID à partir du fichier maintenu par spiffe-helper ou, sauf en Java, appeler directement la SPIFFE Workload API via un fournisseur de jetons. L'approche par fichier est l'intégration la plus simple et fonctionne dans tous les langages du SDK. L'approche par fournisseur de jetons supprime le sidecar mais nécessite un client SPIFFE Workload API dans le langage de votre application.

<Tabs>
  <Tab title="Par fichier avec spiffe-helper">
    Avec spiffe-helper écrivant un JWT-SVID frais dans `/var/run/secrets/anthropic.com/token`, définissez `ANTHROPIC_IDENTITY_TOKEN_FILE` sur ce chemin, ainsi que `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID` et `ANTHROPIC_WORKSPACE_ID`. Le SDK lit le fichier à chaque échange de jeton, de sorte qu'il récupère toujours le SVID le plus récemment renouvelé, et actualise automatiquement le jeton d'accès Anthropic avant son expiration. Consultez [Variables d'environnement](https://platform.claude.com/docs/fr/manage-claude/wif-reference#environment-variables) pour savoir d'où provient chaque valeur.

    <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
      # Lit le JWT-SVID que spiffe-helper écrit dans
      # ANTHROPIC_IDENTITY_TOKEN_FILE, ainsi que ANTHROPIC_FEDERATION_RULE_ID,
      # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et ANTHROPIC_WORKSPACE_ID.
      ant messages create \
        --model claude-opus-5-5 \
        --max-tokens 1024 \
        --message '{role: user, content: "Hello, Claude"}'
      ```

      ```python Python
      import anthropic

      # Lit le JWT-SVID que spiffe-helper écrit dans
      # ANTHROPIC_IDENTITY_TOKEN_FILE, ainsi que ANTHROPIC_FEDERATION_RULE_ID,
      # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et 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";

      // Lit le JWT-SVID que spiffe-helper écrit dans
      // ANTHROPIC_IDENTITY_TOKEN_FILE, ainsi que ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et 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#
      // Lit le JWT-SVID que spiffe-helper écrit dans
      // ANTHROPIC_IDENTITY_TOKEN_FILE, ainsi que ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et 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
      // Lit le JWT-SVID que spiffe-helper écrit dans
      // ANTHROPIC_IDENTITY_TOKEN_FILE, ainsi que ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et 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
      // Lit le JWT-SVID que spiffe-helper écrit dans
      // ANTHROPIC_IDENTITY_TOKEN_FILE, ainsi que ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et 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;

      // Lit le JWT-SVID que spiffe-helper écrit dans
      // ANTHROPIC_IDENTITY_TOKEN_FILE, ainsi que ANTHROPIC_FEDERATION_RULE_ID,
      // ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et 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"

      # Lit le JWT-SVID que spiffe-helper écrit dans
      # ANTHROPIC_IDENTITY_TOKEN_FILE, ainsi que ANTHROPIC_FEDERATION_RULE_ID,
      # ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID et 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="Fournisseur de jetons via la SPIFFE Workload API">
    Sauf en Java, les charges de travail qui intègrent directement un client SPIFFE Workload API peuvent se passer de spiffe-helper et transmettre au SDK un fournisseur de jetons qui récupère un JWT-SVID frais depuis le socket de l'agent. Le SDK invoque le fournisseur avant chaque échange de jeton, de sorte que la charge de travail présente toujours un SVID non expiré. Python ([py-spiffe](https://github.com/HewlettPackard/py-spiffe)) et Go ([go-spiffe](https://github.com/spiffe/go-spiffe)) disposent de clients Workload API matures.

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

      # Se connecte au socket du SPIRE Agent à l'emplacement 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>
      Pour les autres langages, récupérez le JWT-SVID avec le client SPIFFE Workload API de votre environnement d'exécution (ou exécutez `spire-agent api fetch jwt` en ligne de commande), écrivez-le dans un fichier et définissez `ANTHROPIC_IDENTITY_TOKEN_FILE` sur ce chemin comme dans l'onglet par fichier.
    </Note>
  </Tab>
</Tabs>

## Vérifier la configuration

Avant d'intégrer le SDK, récupérez un JWT-SVID directement depuis SPIRE Agent et vérifiez que les claims correspondent à ce que votre règle de fédération attend. Si vous utilisez une autre implémentation SPIFFE, récupérez un JWT-SVID avec son CLI ou son client Workload API et décodez la charge utile de la même manière.

<Note>
  La Workload API atteste le processus appelant. Pour une entrée d'enregistrement Kubernetes, exécutez cette commande à l'intérieur d'un pod qui satisfait les sélecteurs de l'entrée et dans lequel le socket de l'agent est monté (par exemple, en utilisant `kubectl exec`). Sur les VM et le bare metal, exécutez-la en tant qu'utilisateur ou processus correspondant aux sélecteurs `unix:` de l'entrée. L'exécution depuis un shell hôte non attesté renvoie `no identity issued`, ce qui constitue l'échec le plus courant de l'étape de vérification.
</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'
```

L'option `-output json` renvoie la réponse SVID et la réponse bundle sous forme de tableau JSON à deux éléments ; `jq -r '.[0].svids[0].svid'` extrait donc le jeton brut. Sur les anciennes versions de SPIRE sans `-output`, la commande affiche plutôt un bloc étiqueté. Dans ce cas, redirigez la sortie par défaut vers `awk '/^[[:space:]]*eyJ/{print $1; exit}'` pour extraire la ligne du jeton. Vérifiez que `iss` est l'URL de l'OIDC Discovery Provider que vous avez enregistrée, que `sub` est l'identifiant SPIFFE de la charge de travail et que `aud` contient `https://api.anthropic.com`. Exécutez ensuite l'exemple cURL de la section [Acquérir et utiliser le jeton](https://platform.claude.com/docs/fr/manage-claude/wif-providers/spiffe#acquire-and-use-the-token). Un échange réussi renvoie un `access_token` commençant par `sk-ant-oat01-`. Si l'échange échoue avec la réponse opaque `401` `authentication_error` (message `Authentication failed`), consultez la [page d'historique d'authentification](https://platform.claude.com/settings/workload-identity-federation?tab=history) dans la Claude Console pour connaître le motif du refus et reportez-vous à [Dépanner un échange échoué](https://platform.claude.com/docs/fr/manage-claude/wif-reference#troubleshoot-a-failed-exchange). La cause la plus fréquente côté SPIRE est une incohérence entre le `jwt_issuer` de SPIRE Server et l'URL enregistrée comme émetteur de fédération.

## Délimiter votre règle

Les conventions de chemin des identifiants SPIFFE sont définies par l'opérateur ; le matcher `subject_prefix` de la règle de fédération doit donc refléter le schéma de chemin utilisé par vos entrées d'enregistrement. Les schémas courants incluent `spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>` (la valeur par défaut émise par la ressource `ClusterSPIFFEID` dans spire-controller-manager) et `spiffe://<trust-domain>/host/<hostname>/<service>` pour les charges de travail sur VM et bare metal.

<Warning>
  Un `subject_prefix` de `spiffe://prod.example.com/*` correspond à toutes les charges de travail du domaine de confiance. Sans matcher `audience`, la règle accepte également les JWT-SVID émis pour n'importe quelle audience, y compris ceux que la charge de travail a demandés pour des parties utilisatrices sans rapport.
</Warning>

Verrouillez le bloc `match` de la règle sur la portée la plus étroite adaptée à votre cas d'usage :

* **Épingler à une seule charge de travail :** définissez `subject_prefix` sur l'identifiant SPIFFE complet sans `*` final.
* **Toujours définir une audience :** exigez `audience` sur la règle et configurez spiffe-helper (ou l'appel à la Workload API) avec la même valeur afin que les SVID émis pour d'autres parties utilisatrices soient rejetés.
* **Délimiter par segment de chemin :** utilisez `spiffe://prod.example.com/ns/inference/*` pour autoriser toutes les charges de travail enregistrées sous un namespace, et créez une règle et un compte de service Anthropic distincts par namespace plutôt que d'élargir une seule règle.
* **Un émetteur par domaine de confiance :** chaque domaine de confiance SPIRE possède ses propres clés de signature et son propre OIDC Discovery Provider. Enregistrez chacun comme un émetteur de fédération distinct et liez les règles à l'émetteur qui possède les identifiants SPIFFE auxquels elles correspondent.

## Étapes suivantes

<CardGroup cols={2}>
  <Card title="Utiliser WIF avec Okta" icon="lock" href="https://platform.claude.com/docs/fr/manage-claude/wif-providers/okta">
    Fédérez les identités d'applications de service Okta vers l'API Claude avec Workload Identity Federation.
  </Card>

  <Card title="Workload Identity Federation" icon="cloud" href="https://platform.claude.com/docs/fr/manage-claude/workload-identity-federation">
    Authentifiez les charges de travail auprès de l'API Claude avec des jetons d'identité de courte durée provenant de votre propre fournisseur d'identité au lieu de clés API statiques de longue durée.
  </Card>

  <Card title="Référence WIF" icon="book" href="https://platform.claude.com/docs/fr/manage-claude/wif-reference">
    Variables d'environnement, règles de validation, configuration des profils et référence des erreurs pour Workload Identity Federation.
  </Card>

  <Card title="Utiliser WIF avec Kubernetes" icon="cube" href="https://platform.claude.com/docs/fr/manage-claude/wif-providers/kubernetes">
    Authentifiez-vous auprès de l'API Claude depuis des clusters Kubernetes autogérés à l'aide de jetons de compte de service projetés.
  </Card>
</CardGroup>
