Skip to main content

Génération d’un jeton web JSON (JWT) pour une application GitHub

Découvrez comment créer un jeton web JSON (JWT) pour vous authentifier auprès de certains points de terminaison d’API REST avec votre GitHub App.

À propos des jetons web JSON (JWT)

Pour vous authentifier en tant qu’application ou générer un jeton d’accès à l’installation, vous devez générer un jeton web JSON (JWT). Si un point de terminaison d’API REST nécessite un JWT, la documentation de ce point de terminaison indique que vous devez utiliser un JWT pour accéder au point de terminaison.

Votre JWT doit être signé à l’aide de l’algorithme RS256 et contenir les revendications suivantes.

RevendicationSignificationDétails
iatÉmis àHeure de création du jeton JWT. Pour vous protéger contre la dérive de l’horloge, nous vous recommandons de définir cette valeur sur 60 secondes dans le passé et de vous assurer que la date et l’heure de votre serveur sont définies avec précision (par exemple, à l’aide du protocole NTP).
expExpire àHeure d’expiration du jeton JWT, après laquelle il ne peut pas être utilisé pour demander un jeton d’installation. L’heure ne doit pas être de plus de 10 minutes dans le futur.
issÉmetteurL’ID client ou ID d’application de votre GitHub App. Cette valeur est utilisée pour trouver la clé publique appropriée permettant de vérifier la signature du jeton JWT. Vous pouvez trouver votre ID d’application sur la page de paramètres de votre GitHub App. L’utilisation de l’ID client est recommandée. Pour plus d’informations sur la navigation dans la page des paramètres de votre GitHub App, consultez « Modification d’une inscription d’application GitHub ».
algAlgorithme de code d’authentification des messagesVous devez utiliser RS256, que car JWT doit être signé à l’aide de l’algorithme RS256.

Pour utiliser un JWT, passez-le dans l’en-tête Authorization d’une requête d’API. Par exemple :

curl --request GET \
--url "http(s)://HOSTNAME/api/v3/app" \
--header "Accept: application/vnd.github+json" \
--header "Authorization: Bearer YOUR_JWT" \
--header "X-GitHub-Api-Version: 2022-11-28"

Dans la plupart des cas, vous pouvez utiliser Authorization: Bearer ou Authorization: token pour passer un jeton. Toutefois, si vous passez un jeton web JSON (JWT), vous devez utiliser Authorization: Bearer.

Génération d’un jeton JWT (JSON Web Token)

La plupart des langages de programmation ont un package qui peut générer un JWT. Dans tous les cas, vous devez disposer d’une clé privée et de l’ID de votre GitHub App. Pour plus d’informations sur la génération d’une clé privée, consultez « Gestion des clés privées pour les applications GitHub ». Vous pouvez trouver l’ID de votre application avec le point de terminaison de l’API REST GET /app. Pour plus d’informations, consultez « Applications » dans la documentation de l’API REST.

Remarque : Au lieu de créer un JWT, vous pouvez utiliser les SDK Octokit de GitHub pour vous authentifier en tant qu’application. Le Kit de développement logiciel (SDK) se chargera de générer un JWT pour vous, et régénérera le JWT une fois ce dernier arrivé à expiration. Pour plus d’informations, consultez « Écriture de scripts avec l’API REST et JavaScript ».

Exemple : Utilisation de Ruby pour générer un JWT

Remarque : Vous devez exécuter gem install jwt pour installer le package jwt afin d’utiliser ce script.

Dans l’exemple suivant, remplacez YOUR_PATH_TO_PEM par le chemin d’accès au fichier où votre clé privée est stockée. Remplacez YOUR_APP_ID par l’ID de votre application. Veillez à placer les valeurs YOUR_PATH_TO_PEM et YOUR_APP_ID entre guillemets doubles.

require 'openssl'
require 'jwt'  # https://rubygems.org/gems/jwt

# Private key contents
private_pem = File.read("YOUR_PATH_TO_PEM")
private_key = OpenSSL::PKey::RSA.new(private_pem)

# Generate the JWT
payload = {
  # issued at time, 60 seconds in the past to allow for clock drift
  iat: Time.now.to_i - 60,
  # JWT expiration time (10 minute maximum)
  exp: Time.now.to_i + (10 * 60),
  
# GitHub App's client ID
  iss: "YOUR_CLIENT_ID"
}

jwt = JWT.encode(payload, private_key, "RS256")
puts jwt

Exemple : Utilisation de Python pour générer un JWT

Remarque : Vous devez exécuter pip install PyJWT pour installer le package PyJWT afin d’utiliser ce script.

Python
#!/usr/bin/env python3
import sys
import time

import jwt

# Get PEM file path
if len(sys.argv) > 1:
    pem = sys.argv[1]
else:
    pem = input("Enter path of private PEM file: ")

# Get the Client ID
if len(sys.argv) > 2:
    client_id = sys.argv[2]
else:
    client_id = input("Enter your Client ID: ")

# Open PEM
with open(pem, 'rb') as pem_file:
    signing_key = pem_file.read()

payload = {
    # Issued at time
    'iat': int(time.time()),
    # JWT expiration time (10 minutes maximum)
    'exp': int(time.time()) + 600,
    
    # GitHub App's client ID
    'iss': client_id
}

# Create JWT
encoded_jwt = jwt.encode(payload, signing_key, algorithm='RS256')

print(f"JWT:  {encoded_jwt}")

Ce script vous invite à entrer le chemin du fichier où votre clé privée est stockée et l’ID de votre application. Vous pouvez également passer ces valeurs en tant qu’arguments inline lorsque vous exécutez le script.

Exemple : utilisation de Bash pour générer un JWT

Remarque : vous devez transmettre votre ID client et le chemin d’accès du fichier où votre clé privée est stockée en tant qu’arguments lors de l’exécution de ce script.

Bash
#!/usr/bin/env bash

set -o pipefail

client_id=$1 # Client ID as first argument

pem=$( cat $2 ) # file path of the private key as second argument

now=$(date +%s)
iat=$((${now} - 60)) # Issues 60 seconds in the past
exp=$((${now} + 600)) # Expires 10 minutes in the future

b64enc() { openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n'; }

header_json='{
    "typ":"JWT",
    "alg":"RS256"
}'
# Header encode
header=$( echo -n "${header_json}" | b64enc )

payload_json="{
    \"iat\":${iat},
    \"exp\":${exp},
    \"iss\":\"${client_id}\"
}"
# Payload encode
payload=$( echo -n "${payload_json}" | b64enc )

# Signature
header_payload="${header}"."${payload}"
signature=$(
    openssl dgst -sha256 -sign <(echo -n "${pem}") \
    <(echo -n "${header_payload}") | b64enc
)

# Create JWT
JWT="${header_payload}"."${signature}"
printf '%s\n' "JWT: $JWT"

Exemple : utilisation de PowerShell pour générer un JWT

Dans l’exemple suivant, remplacez YOUR_PATH_TO_PEM par le chemin d’accès au fichier où votre clé privée est stockée. Remplacez YOUR_CLIENT_ID par l’ID de votre application. Veillez à placer les valeurs de YOUR_PATH_TO_PEM entre guillemets doubles.

PowerShell
#!/usr/bin/env pwsh

$client_id = YOUR_CLIENT_ID

$private_key_path = "YOUR_PATH_TO_PEM"

$header = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject @{
  alg = "RS256"
  typ = "JWT"
}))).TrimEnd('=').Replace('+', '-').Replace('/', '_');

$payload = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject @{
  iat = [System.DateTimeOffset]::UtcNow.AddSeconds(-10).ToUnixTimeSeconds()
  exp = [System.DateTimeOffset]::UtcNow.AddMinutes(10).ToUnixTimeSeconds()
    iss = $client_id
}))).TrimEnd('=').Replace('+', '-').Replace('/', '_');

$rsa = [System.Security.Cryptography.RSA]::Create()
$rsa.ImportFromPem((Get-Content $private_key_path -Raw))

$signature = [Convert]::ToBase64String($rsa.SignData([System.Text.Encoding]::UTF8.GetBytes("$header.$payload"), [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)).TrimEnd('=').Replace('+', '-').Replace('/', '_')
$jwt = "$header.$payload.$signature"
Write-Host $jwt