Skip to main content

Generación de un token web JSON (JWT) para una aplicación de GitHub

Aprende a crear un JSON Web Token (JWT) para autenticarte en determinados puntos de conexión de API REST con tu GitHub App.

Sobre JSON Web Token (JWT)

Para la autenticación como una aplicación o la generación de un token de acceso de instalación, debes generar un JSON Web Token (JWT). Si un punto de conexión de la API de REST necesita un JWT, la documentación de ese punto de conexión indicará que debes usar un JWT para acceder al punto de conexión.

El JWT tiene que estar firmado con el algoritmo y contener las notificaciones siguientes.

NotificaciónSignificadoDetalles
iatEmitido a lasLa hora a la que se creó el JWT. Para protegerte contra el desfase del reloj, se recomienda establecer estos 60 segundos en el pasado y asegurarse de que la fecha y hora del servidor se establecen con precisión (por ejemplo, mediante el Protocolo de hora de red).
expExpira a lasLa hora de expiración del JWT, después de la cual no se puede usar para solicitar un token de instalación. El valor de tiempo debe ser máximo 10 minutos después.
issEmisorEl id. de cliente o id. de aplicación de GitHub App. Este valor se usa para buscar la clave pública correcta para comprobar la firma del JWT. Puede encontrar el identificador de la aplicacións en la página de configuración para su GitHub App. Se recomienda usar el identificador de cliente. Para obtener más información sobre cómo navegar a la página de configuración de su GitHub App, consulte AUTOTITLE.
algAlgoritmo de código de autenticación de mensajesDebería ser , ya que el JWT debe firmarse mediante el algoritmo .

Para usar un JWT, pásalo en el encabezado de una solicitud de API. Por ejemplo:

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"

En la mayoría de los casos, puedes usar Authorization: Bearer o Authorization: token para pasar un token. Sin embargo, si vas a pasar un token web JSON (JWT), debes usar Authorization: Bearer.

Generación de un JSON Web Token (JWT)

La mayoría de los lenguajes de programación tienen un paquete que puede generar un JWT. En todos los casos, debes tener una clave privada y el id. de tu GitHub App. Para obtener más información sobre cómo generar una clave privada, consulte AUTOTITLE. Puedes encontrar el id. de la aplicación con el punto de conexión de la API de REST . Para obtener más información, consulte Aplicaciones en la documentación de la API de REST.

Nota:

En vez de crear un JWT, puede usar los SDK de Octokit de GitHub para autenticarse como aplicación. El SDK se encargará de generar un JWT automáticamente y volverá a generar el JWT una vez que expire el token. Para obtener más información, consulte Scripting con la API REST y JavaScript.

Ejemplo: Uso de Ruby para generar un JWT

Nota:

Debe ejecutar para instalar el paquete para poder usar este script.

En el ejemplo siguiente, reemplaza por la ruta de acceso del archivo donde se almacena la clave privada. Reemplace por el ID de la aplicación. Asegúrese de incluir los valores de y entre comillas dobles.

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

Ejemplo: Uso de Python para generar un JWT

Nota:

Debe ejecutar para instalar los paquetes y para poder usar este 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}")

Este script le pedirá la ruta de acceso del archivo donde se almacena la clave privada y el ID de cliente de su aplicación. Como alternativa, puedes pasar esos valores como argumentos insertados al ejecutar el script.

Ejemplo: Uso de Bash para generar un JWT

Nota:

Debe pasar Client ID y la ruta donde se almacena el archivo de la clave privada como argumentos al ejecutar este script.

Bash
#!/usr/bin/env bash

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"

Ejemplo: Uso de PowerShell para generar un JWT

En el ejemplo siguiente, reemplaza por la ruta de acceso del archivo donde se almacena la clave privada. Reemplace por el ID de la aplicación. Asegúrese de poner los valores para entre comillas dobles.

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