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, afin que vos tâches de CI puissent appeler l'API Claude sans qu'un secret ANTHROPIC_API_KEY ne soit stocké dans votre dépôt.
La revendication sub du jeton encode le dépôt et le contexte du déclencheur. Pour un push vers une branche, elle prend 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 sur cette revendication (et d'autres, telles que repository_owner et ref) pour déterminer 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 l'audience de votre choix 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 fonctionnalité 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é contient des revendications qui décrivent l'exécution du workflow. Votre règle de fédération effectue une correspondance sur 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.
Suivez le guide de configuration pour enregistrer un émetteur de fédération, créer un compte de service Anthropic et créer une règle de fédération dans la Claude Console. Utilisez ces valeurs spécifiques à GitHub Actions.
É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 effectue leur rotation.
{
"name": "github-actions",
"issuer_url": "https://token.actions.githubusercontent.com",
"jwks_source": "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 les workflows autorisés à 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 à 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-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(message.content[0].text)Chaque jeton d'identité émis par GitHub expire environ cinq minutes après son émission. Le point de terminaison de requête 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 encapsulez-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 du 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 que le format de la revendication sub 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 à 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é 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?