Informationen zu JSON Web Token (JWTs)
Zur Authentifizierung als App oder zum Generieren eines Installationszugriffstokens musst du ein JSON Web Token (JWT) generieren. Wenn ein REST-API-Endpunkt ein JWT erfordert, wird in der Dokumentation für den jeweiligen Endpunkt angegeben, dass für den Zugriff ein JWT erforderlich ist.
Dein JWT muss mit dem RS256
-Algorithmus signiert sein und die folgenden Ansprüche enthalten.
Anspruch | Bedeutung | Details |
---|---|---|
iat | Ausgestellt um | Die Zeitpunkt, zu dem die JWT-Instanz erstellt wurde. Zum Schutz vor Uhrenfehlern solltest du diese 60 Sekunden in der Vergangenheit festlegen und sicherstellen, dass Datum und Uhrzeit deines Servers genau eingestellt sind (z. B. mithilfe des Network Time Protocol). |
exp | Läuft ab | Dies ist die Ablaufzeit der JWT-Methode, nach der sie nicht mehr zum Anfordern eines Installationstokens verwendet werden kann. Der Zeitpunkt darf nicht später als 10 Minuten in der Zukunft liegen. |
iss | Issuer (Aussteller) | Die Anwendungs-ID Ihrer GitHub App. Dieser Wert wird verwendet, um den richtigen öffentlichen Schlüssel zu finden, um die Signatur der JWT-Methode zu überprüfen. Du findest die ID deiner App auf der Einstellungsseite deiner GitHub App. Weitere Informationen zum Navigieren zur Einstellungsseite deiner GitHub App findest du unter Ändern einer GitHub-App-Registrierung. |
alg | Nachrichtenauthentifizierungscode-Algorithmus | Dies sollte RS256 sein, da deine JWT-Instanz mit dem RS256 -Algorithmus signiert werden muss. |
Um ein JWT zu verwenden, übergib es im Authorization
-Header einer API-Anforderung. Beispiel:
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"
In den meisten Fällen kannst du Authorization: Bearer
oder Authorization: token
verwenden, um ein Token zu übergeben. Wenn du jedoch ein JWT (JSON Web Token) übergibst, musst du Authorization: Bearer
verwenden.
Generieren von JSON Web Token (JWT)
Die meisten Programmiersprachen verfügen über ein Paket, das ein JWT generieren kann. In allen Fällen benötigst du einen privaten Schlüssel und die ID deiner GitHub App. Weitere Informationen zum Generieren eines privaten Schlüssels findest du unter Verwalten privater Schlüssel für GitHub-Apps. Du kannst die ID deiner App mit dem GET /app
REST-API-Endpunkt ermitteln. Weitere Informationen findest du in der REST-API-Dokumentation unter Apps.
Note
Du kannst Octokit-SDKs von GitHub zum Authentifizieren als App verwenden, anstatt ein JWT zu erstellen. Das SDK kümmert sich um die Generierung eines JWT für dich und generiert das JWT, sobald das Token abläuft. Weitere Informationen findest du unter Skripterstellung mit der REST-API und JavaScript.
Beispiel: Verwenden von Ruby zum Generieren eines JWT
Note
Du musst zum Installieren des jwt
-Pakets gem install jwt
ausführen, um dieses Skript verwenden zu können.
Ersetze im folgenden Beispiel YOUR_PATH_TO_PEM
durch den Dateipfad, in dem dein privater Schlüssel gespeichert ist. Ersetze YOUR_APP_ID
durch die ID deiner App. Achte darauf, dass die Werte für YOUR_PATH_TO_PEM
und YOUR_APP_ID
in doppelte Anführungszeichen eingeschlossen werden.
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 app ID
iss: "YOUR_APP_ID"
}
jwt = JWT.encode(payload, private_key, "RS256")
puts jwt
Beispiel: Verwenden von Python zum Generieren eines JWT
Note
Du musst zum Installieren des PyJWT
-Pakets pip install PyJWT
ausführen, um dieses Skript verwenden zu können.
#!/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 App ID if len(sys.argv) > 2: app_id = sys.argv[2] else: app_id = input("Enter your APP 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 app ID 'iss': app_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 App ID
if len(sys.argv) > 2:
app_id = sys.argv[2]
else:
app_id = input("Enter your APP 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 app ID
'iss': app_id
}
# Create JWT
encoded_jwt = jwt.encode(payload, signing_key, algorithm='RS256')
print(f"JWT: {encoded_jwt}")
Dieses Skript fragt dich nach dem Dateipfad, in dem dein privater Schlüssel gespeichert ist, und der ID deiner App. Alternativ kannst du diese Werte als Inlineargumente übergeben, wenn du das Skript ausführst.
Beispiel: Verwenden von Bash zum Generieren eines JWT
Note
Du musst deine App-ID und den Dateipfad, in dem dein privater Schlüssel gespeichert ist, als Argumente übergeben, wenn du dieses Skript ausführst.
#!/usr/bin/env bash set -o pipefail app_id=$1 # App 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\":\"${app_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
app_id=$1 # App 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\":\"${app_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"
Beispiel: Verwenden von PowerShell zum Generieren eines JWT
Ersetze im folgenden Beispiel YOUR_PATH_TO_PEM
durch den Dateipfad, in dem dein privater Schlüssel gespeichert ist. Ersetze YOUR_APP_ID
durch die ID deiner App. Achten Sie darauf, dass die Werte für YOUR_PATH_TO_PEM
in doppelte Anführungszeichen eingeschlossen werden.
#!/usr/bin/env pwsh $app_id = YOUR_APP_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 = $app_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
$app_id = YOUR_APP_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 = $app_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