JWT(JSON Web Token) 정보
앱으로 인증하거나 설치 액세스 토큰을 생성하려면 JWT(JSON Web Token)를 생성해야 합니다. REST API 엔드포인트가 JWT를 필요한 경우 해당 엔드포인트에 대한 설명서에는 JWT를 사용하여 엔드포인트에 액세스해야 함을 나타냅니다.
JWT는 RS256
알고리즘을 사용하여 서명되어야 하며 다음 클레임을 포함해야 합니다.
클레임 | 의미 | 세부 정보 |
---|---|---|
iat | 발급 시간 | JWT가 만들어질 시간입니다. 클록 드리프트를 방지하려면 이를 과거 60초로 설정하고 서버의 날짜와 시간을 정확하게 설정하는 것이 좋습니다(예: 네트워크 타임 프로토콜 사용). |
exp | 만료 시간 | JWT의 만료 시간이며, 그 후에는 설치 토큰을 요청하는 데 사용할 수 없습니다. 시간은 앞으로 10분 이내여야 합니다. |
iss | Issuer | GitHub App의 애플리케이션 ID. 이 값은 JWT의 서명을 확인하는 데 적합한 공개 키를 찾는 데 사용됩니다. 앱의 ID는 GitHub App의 설정 페이지에서 찾을 수 있습니다. GitHub App의 설정 페이지로 이동하는 방법에 대한 자세한 내용은 "GitHub 앱 등록 수정"을(를) 참조하세요. |
alg | 메시지 인증 코드 알고리즘 | 이것은 RS256 알고리즘을 사용하여 JWT가 서명되어야 하기 때문에 RS256 여야 합니다. |
JWT를 사용하려면 API 요청의 Authorization
헤더에 전달합니다. 예시:
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"
대부분의 경우 Authorization: Bearer
또는 Authorization: token
을 사용하여 전달할 수 있습니다. 그러나 JWT(JSON 웹 토큰)를 전달하는 경우 Authorization: Bearer
를 사용해야 합니다.
JWT(JSON Web Token) 생성
대부분의 프로그래밍 언어에는 JWT를 생성할 수 있는 패키지가 있습니다. 모든 경우에 GitHub App의 프라이빗 키와 ID가 있어야 합니다. 프라이빗 키 생성에 관한 자세한 내용은 "GitHub 앱에 대한 프라이빗 키 관리"을 참조하세요. GET /app
REST API 엔드포인트를 사용하여 앱의 ID를 찾을 수 있습니다. 자세한 내용은 REST API 설명서에 있는 "앱"을 참조하세요.
참고: JWT를 만드는 대신 GitHub의 Oktokit SDK를 사용하여 앱으로 인증할 수 있습니다. SDK는 JWT 생성을 처리하고 토큰이 만료되면 JWT를 다시 생성합니다. 자세한 내용은 "REST API 및 JavaScript를 사용하여 스크립팅"을 참조하세요.
예: 루비를 사용하여 JWT 생성
참고: 이 스크립트를 사용하려면 jwt
패키지를 설치하기 위해 gem install jwt
을(를) 실행해야 합니다.
다음 예제에서는 YOUR_PATH_TO_PEM
을(를) 프라이빗 키가 저장된 파일 경로로 바꿉니다. YOUR_APP_ID
을(를) 앱의 ID으로 바꿉니다. YOUR_PATH_TO_PEM
및 YOUR_APP_ID
값을 큰따옴표로 묶어야 합니다.
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
예: 파이썬을 사용하여 JWT 생성
참고: 이 스크립트를 사용하려면 jwt
패키지를 설치하기 위해 pip install jwt
을(를) 실행해야 합니다.
#!/usr/bin/env python3 from jwt import JWT, jwk_from_pem import time import sys # 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 = jwk_from_pem(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 jwt_instance = JWT() encoded_jwt = jwt_instance.encode(payload, signing_key, alg='RS256') print(f"JWT: {encoded_jwt}")
#!/usr/bin/env python3
from jwt import JWT, jwk_from_pem
import time
import sys
# 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 = jwk_from_pem(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
jwt_instance = JWT()
encoded_jwt = jwt_instance.encode(payload, signing_key, alg='RS256')
print(f"JWT: {encoded_jwt}")
이 스크립트는 프라이빗 키가 저장된 파일 경로와 앱의 ID를 표시합니다. 또는 스크립트를 실행할 때 이러한 값을 인라인 인수로 전달할 수 있습니다.
예제: Bash를 사용하여 JWT 생성
참고: 이 스크립트를 실행할 때 앱 ID 및 개인 키가 저장된 파일 경로를 인수로 전달해야 합니다.
#!/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"
예제: PowerShell을 사용하여 JWT 생성
다음 예제에서는 YOUR_PATH_TO_PEM
을(를) 프라이빗 키가 저장된 파일 경로로 바꿉니다. YOUR_APP_ID
을(를) 앱의 ID로 바꿉니다. YOUR_PATH_TO_PEM
값을 큰따옴표로 묶어야 합니다.
#!/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