À 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.
Revendication | Signification | Dé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). |
exp | Expire à | 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 | Émetteur | L’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 ». |
alg | Algorithme de code d’authentification des messages | Vous 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 "https://api.github.com/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.
Note
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
Note
Vous devez exécuter gem install jwt
pour installer le paquer 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
Note
Vous devez exécuter pip install PyJWT
pour installer le paquer PyJWT
afin d’utiliser ce script.
#!/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}")
#!/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
Note
Vous devez passer votre Client ID et le chemin d'accès au fichier où votre clé privée est stockée comme arguments lors de l'exécution de ce script.
#!/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"
#!/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.
#!/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
#!/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