Ă 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 | 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 rechercher les IDs de lâapplication sur la page des paramĂštres de votre GitHub App. Lâutilisation de lâID client est recommandĂ©e. Pour plus dâinformations sur la navigation vers la page des paramĂštres pour 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.
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 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_CLIENT_ID
par lâID de votre application. Veillez Ă placer les valeurs YOUR_PATH_TO_PEM
et YOUR_CLIENT_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 cryptography
pour installer les packages PyJWT
et cryptography
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
Remarque
Vous devez transmettre votre ID client et le chemin dâaccĂšs au fichier oĂč votre clĂ© privĂ©e est stockĂ©e en tant quâ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