Chaque exécution de workflow GitHub Actions peut demander un jeton d'identité signé auprès de l'émetteur hébergé de GitHub à l'adresse https://token.actions.githubusercontent.com. Avec la « Workload Identity Federation » (fédération d'identité de charge de travail), votre workflow échange ce jeton contre un jeton d'accès Anthropic de courte durée, de sorte que vos tâches CI peuvent appeler l'API Claude sans secret ANTHROPIC_API_KEY stocké dans votre dépôt.
La revendication sub du jeton encode le dépôt et le contexte de déclenchement. Pour un push vers une branche, elle a la forme repo:<owner>/<repo>:ref:refs/heads/<branch>. Les exécutions de pull request utilisent repo:<owner>/<repo>:pull_request, et les déploiements contrôlés par environnement utilisent repo:<owner>/<repo>:environment:<name>. Votre règle de fédération effectue une correspondance avec cette revendication (et d'autres, telles que repository_owner et ref) pour décider quelles exécutions de workflow sont autorisées à s'authentifier.
id-token: write.GitHub n'émet un jeton d'identité qu'aux tâches qui le demandent explicitement. Ajoutez la permission id-token: write au niveau du workflow ou de la tâche :
permissions:
id-token: write
contents: readÀ l'intérieur de la tâche, le runner expose deux variables d'environnement : ACTIONS_ID_TOKEN_REQUEST_URL et ACTIONS_ID_TOKEN_REQUEST_TOKEN. Appelez l'URL de requête avec le jeton de requête comme identifiant bearer et votre audience choisie comme paramètre de requête, puis écrivez le « JSON Web Token » (jeton Web JSON), ou JWT, retourné dans un fichier :
- name: Fetch GitHub OIDC token
run: |
curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://api.anthropic.com" \
| jq -r .value > /tmp/gha-jwtSi vous préférez JavaScript, actions/github-script expose la même capacité via core.getIDToken(audience) :
- name: Fetch GitHub OIDC token
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
const token = await core.getIDToken('https://api.anthropic.com');
fs.writeFileSync('/tmp/gha-jwt', token);Le jeton décodé porte des revendications qui décrivent l'exécution du workflow. Votre règle de fédération effectue une correspondance avec celles-ci :
{
"iss": "https://token.actions.githubusercontent.com",
"sub": "repo:your-org/your-repo:ref:refs/heads/main",
"aud": "https://api.anthropic.com",
"repository": "your-org/your-repo",
"repository_owner": "your-org",
"ref": "refs/heads/main",
"sha": "abc123...",
"workflow": "CI",
"actor": "octocat",
"event_name": "push"
}Consultez la référence des revendications de sujet OIDC de GitHub pour la liste complète des formats de sub.
Dans la Claude Console, ouvrez Settings → Workload identity, cliquez sur Connect workload, puis sélectionnez la tuile GitHub Actions. L'assistant vous guide à travers 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 :
Émetteur de fédération : GitHub publie publiquement son document de découverte OIDC et son JWKS, utilisez donc le mode découverte. Anthropic actualise automatiquement les clés lorsque GitHub les fait tourner.
{
"name": "github-actions",
"issuer_url": "https://token.actions.githubusercontent.com",
"jwks": { "type": "discovery" }
}Règle de fédération : Ne faites correspondre que les exécutions de workflow auxquelles vous avez l'intention de faire confiance. Consultez Restreindre quels workflows peuvent s'authentifier pour savoir comment délimiter ces revendications en toute sécurité.
{
"name": "gha-main",
"issuer_id": "fdis_...",
"match": {
"subject_prefix": "repo:your-org/your-repo:ref:refs/heads/main",
"audience": "https://api.anthropic.com",
"claims": {
"repository_owner": "your-org"
}
},
"target": {
"type": "service_account",
"service_account_id": "svac_..."
},
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}Soyez aussi spécifique que la charge de travail le permet. N'assouplissez subject_prefix en repo:your-org/your-repo:* (associé à une contrainte claims.ref) que si la règle doit correspondre à plusieurs types d'événements provenant du même dépôt, car le segment final de sub varie entre les événements ref:..., environment:... et pull_request.
Définissez les variables d'environnement de fédération sur la tâche et appelez le SDK normalement. Anthropic() lit ANTHROPIC_IDENTITY_TOKEN_FILE, échange le JWT lors de la première requête et actualise automatiquement le jeton d'accès avant son expiration.
import anthropic
# Lit ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID,
# ANTHROPIC_SERVICE_ACCOUNT_ID, ANTHROPIC_WORKSPACE_ID et ANTHROPIC_IDENTITY_TOKEN_FILE
# depuis l'environnement du job.
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(next(block.text for block in message.content if block.type == "text"))Chaque jeton d'identité émis par GitHub expire environ cinq minutes après son émission. Le point de terminaison de demande de jeton (ACTIONS_ID_TOKEN_REQUEST_URL) reste valide pendant toute la durée de la tâche, vous pouvez donc récupérer un nouveau jeton à tout moment. Le SDK échange le jeton lors de la première utilisation et met en cache le jeton d'accès Anthropic résultant. Pour les tâches qui s'exécutent plus longtemps que la durée de vie du jeton Anthropic, le SDK relit ANTHROPIC_IDENTITY_TOKEN_FILE à chaque actualisation ; réexécutez donc périodiquement l'étape de récupération (ou enveloppez-la dans une boucle en arrière-plan) pour maintenir le fichier à jour. Vous pouvez également passer au SDK un callback fournisseur de jeton qui appelle directement ACTIONS_ID_TOKEN_REQUEST_URL au lieu d'utiliser le chemin de fichier.
Un échange réussi retourne un access_token commençant par sk-ant-oat01- et une valeur expires_in en secondes. En cas de 400 invalid_grant, consultez Dépanner un échange échoué ; la cause la plus courante côté GitHub Actions est un format de revendication sub qui ne correspond pas (son segment final varie entre les événements ref:..., environment:... et pull_request).
Un subject_prefix de repo:your-org/* seul correspond à tous les dépôts de votre organisation, et sans contrainte ref, il correspond également aux exécutions pull_request déclenchées depuis des forks. Toute personne pouvant ouvrir une pull request sur un dépôt correspondant pourrait obtenir un jeton Anthropic fédéré.
Verrouillez le bloc match de la règle sur la portée la plus étroite qui convient à votre cas d'usage :
subject_prefix: "repo:your-org/your-repo:*" afin que les autres dépôts de l'organisation ne correspondent pas."ref": "refs/heads/main" (ou votre branche de release) sous claims afin que les exécutions de pull request et les branches de fonctionnalités ne correspondent pas."repository_owner": "your-org" sous claims comme vérification de défense en profondeur contre les cas limites d'analyse de sub.subject_prefix: "repo:your-org/your-repo:environment:production" et protégez cet environnement avec des réviseurs requis dans GitHub.Was this page helpful?