Publicado el 09/03/2026 22 visitas KW: verificar jwt rs256 con jwks en español

Cómo verificar un JWT RS256 con JWKS paso a paso (kid, rotación y errores típicos)

Cómo verificar un JWT RS256 con JWKS paso a paso (kid, rotación y errores típicos) Verificar un JWT (JSON Web Token) firmado con RS256 usando JWKS (JSON We

Cómo verificar un JWT RS256 con JWKS paso a paso (kid, rotación y errores típicos)

Verificar un JWT (JSON Web Token) firmado con RS256 usando JWKS (JSON Web Key Set) es crucial para la seguridad de tus aplicaciones. Esta guía te mostrará cómo hacerlo de forma segura y eficiente, abordando los errores más comunes y proporcionando ejemplos prácticos. Si necesitas validar la autenticidad de un token emitido por un proveedor externo (como Google, Auth0, o cualquier otro que use OAuth/OIDC), este artículo es para ti.

¿Por qué verificar JWT RS256 con JWKS?

El algoritmo RS256 es ampliamente utilizado porque permite verificar la integridad y autenticidad de un JWT sin necesidad de compartir la clave secreta utilizada para firmarlo. El proveedor de identidad (IdP) firma el token con su clave privada, y tú, como consumidor, lo verificas con la clave pública que el IdP publica en formato JWKS. Esto es fundamental para:

  • Confirmar la identidad del usuario: Asegura que el token fue emitido por el proveedor legítimo.
  • Garantizar la integridad del token: Detecta cualquier modificación no autorizada del contenido del token.
  • Control de acceso: Basado en la información del token, puedes autorizar o denegar el acceso a recursos protegidos.

Paso a paso: Verifica tu JWT RS256 con JWKS

Sigue estos pasos para verificar un JWT RS256 utilizando JWKS. Cada paso incluye una explicación detallada y consejos prácticos para evitar errores.

1. Decodifica el JWT y examina el Header

El primer paso es decodificar el JWT. Esto te permitirá inspeccionar el contenido del header y el payload sin verificar la firma (todavía). Puedes usar herramientas online como jwt.io o la extensión JWT Debugger PRO. Presta especial atención a:

  • alg (Algoritmo): Asegúrate de que el valor sea RS256. Si es diferente, y no esperabas otro algoritmo, la verificación fallará (o el token podría ser fraudulento).
  • kid (Key ID): Este identificador te indicará qué clave del JWKS debes usar para verificar la firma.
  • typ (Type): Normalmente es JWT. Aunque no es crítico para la verificación, ayuda a identificar el tipo de token.

Ejemplo: Considera un header como este:

{
  "alg": "RS256",
  "kid": "your-key-id",
  "typ": "JWT"
}

Si alg no es RS256, la verificación no procederá. Si el kid no existe en tu JWKS, deberás revisar tu configuración.

2. Obtén el JWKS (JSON Web Key Set)

El JWKS es un conjunto de claves públicas en formato JSON. Normalmente, el IdP publica el JWKS en una URL específica. El estándar OIDC (OpenID Connect) define una URL predecible: /.well-known/openid-configuration, que contiene la URL del JWKS en el campo jwks_uri.

Ejemplo:

{
  "issuer": "https://tu-idp.com",
  "jwks_uri": "https://tu-idp.com/.well-known/jwks.json"
}

Utiliza la URL de jwks_uri para obtener el JWKS. En algunos casos, el IdP podría proporcionar directamente la URL del JWKS, por ejemplo: https://tu-idp.com/jwks.json. Importante: Evita hardcodear la URL del JWKS siempre que sea posible. Usa la configuración estándar de OIDC para que tu aplicación se adapte automáticamente a los cambios del IdP.

3. Selecciona la clave correcta por kid

El JWKS puede contener múltiples claves. Para seleccionar la clave correcta, usa el valor de kid del header del JWT. Busca la clave en el JWKS que coincida con ese kid.

Ejemplo: Un JWKS podría lucir así:

[
  {
    "kty": "RSA",
    "kid": "key-id-1",
    "use": "sig",
    "alg": "RS256",
    "n": "...",
    "e": "AQAB"
  },
  {
    "kty": "RSA",
    "kid": "key-id-2",
    "use": "sig",
    "alg": "RS256",
    "n": "...",
    "e": "AQAB"
  }
]

Si el kid en el header del JWT es key-id-2, debes usar esa clave para la verificación.

4. Verifica la firma

Este es el paso crítico. Necesitas verificar la firma del JWT usando la clave pública seleccionada. La firma se calcula sobre el string header.payload (Base64URL), no sobre el JSON serializado. Usa una librería de verificación de JWT para tu lenguaje de programación.

Ejemplo (Node.js con jsonwebtoken y jwks-rsa):

import jwt from "jsonwebtoken";
import jwksClient from "jwks-rsa";

const client = jwksClient({ jwksUri: "https://tu-idp.com/.well-known/jwks.json" });

function getKey(header, cb) {
  client.getSigningKey(header.kid, function(err, key) {
    if (err) {
      return cb(err);
    }
    cb(null, key.getPublicKey());
  });
}

jwt.verify(token, getKey, { algorithms: ["RS256"] }, (err, decoded) => {
  if (err) {
    console.error("Error al verificar el token:", err);
  } else {
    console.log("Token verificado:", decoded);
  }
});

Consejo: Asegúrate de especificar el algoritmo RS256 en la configuración de la librería de verificación. Rechaza cualquier otro algoritmo.

5. Valida los Claims (exp, nbf, iat) y aplica Clock Skew

Una vez verificada la firma, debes validar los claims del payload, especialmente:

  • exp (Expiration Time): El tiempo de expiración del token. Rechaza tokens expirados.
  • nbf (Not Before): El tiempo antes del cual el token no es válido. Valida que el tiempo actual sea posterior a este valor.
  • iat (Issued At): El tiempo en que se emitió el token. Aunque no es crítico, puede ser útil para fines de auditoría.

Clock Skew: Aplica un margen de tolerancia (clock skew) para tener en cuenta las diferencias de tiempo entre los servidores. Por ejemplo, podrías permitir un margen de 60 segundos (o más, según tus necesidades) en la validación de exp y nbf.

Ejemplo (JavaScript):

const now = Math.floor(Date.now() / 1000); // Tiempo actual en segundos (Unix timestamp)
const clockSkew = 60; // Tolerancia de 60 segundos

if (decoded.exp < now - clockSkew) {
  // Token expirado
  console.error("Token expirado");
}
if (decoded.nbf > now + clockSkew) {
  // Token no válido aún
  console.error("Token no válido");
}

Errores comunes y cómo solucionarlos

Estos son algunos de los errores más comunes que encuentras al verificar JWT RS256, y cómo puedes solucionarlos.

  • Error: Invalid signature o firma inválida.
    Solución:
    • Verifica que el algoritmo especificado en la configuración de la librería (por ejemplo, en jwt.verify) coincida con el valor de alg en el header del JWT (debe ser RS256).
    • Asegúrate de que estás usando la clave pública correcta. Revisa el kid en el header del JWT y compara con las claves disponibles en el JWKS.
    • Comprueba que no haya errores al obtener el JWKS (por ejemplo, problemas de red, URL incorrecta).
  • Error: kid no coincide con ninguna clave en el JWKS.
    Solución:
    • Verifica que el JWKS que estás utilizando es el correcto. Comprueba la URL y asegúrate de que estás obteniendo el JWKS de la fuente correcta. Considera problemas de caché.
    • Revisa si hay diferencias entre entornos (desarrollo, staging, producción). Es posible que estés usando un JWKS diferente en cada entorno.
    • Implementa un mecanismo para refrescar el JWKS periódicamente (con un TTL) y manejar la rotación de claves.
  • Error: Formato de clave incorrecto.
    Solución:
    • Asegúrate de que la clave pública esté en el formato correcto (PEM o JWK). Algunas librerías pueden requerir un formato específico.
    • Si estás usando un certificado en formato X.509, extrae la clave pública o conviértelo al formato correcto (por ejemplo, con OpenSSL).
  • Error: Problemas con el reloj (exp/nbf).
    Solución:
    • Sincroniza los relojes de tus servidores con un servidor NTP.
    • Aplica un margen de tolerancia (clock skew) al validar los claims exp y nbf.
  • Error: Caracteres invisibles o token truncado.
    Solución:
    • Asegúrate de que el token no ha sido modificado durante la copia o transmisión (ej. espacios adicionales, saltos de línea).
    • Compara la longitud del token con la esperada.
    • Utiliza herramientas como JWT Debugger Pro o jwt.io para inspeccionar el token y detectar posibles problemas.

Ejemplos prácticos con código

A continuación, encontrarás ejemplos de código en diferentes lenguajes de programación para ayudarte a empezar a verificar JWT RS256.

Obtener el JWKS (cURL)

Puedes usar curl para obtener el JWKS desde la URL proporcionada por el IdP. Este comando es útil para la depuración y para verificar que la URL del JWKS es accesible.

curl -s https://tu-idp.com/.well-known/jwks.json | jq '.'

Node.js con jwks-rsa y jsonwebtoken

Este ejemplo muestra cómo verificar un JWT RS256 en Node.js, usando las librerías jwks-rsa para obtener las claves públicas del JWKS y jsonwebtoken para la verificación.

import jwt from "jsonwebtoken";
import jwksClient from "jwks-rsa";

const client = jwksClient({
  jwksUri: "https://tu-idp.com/.well-known/jwks.json",
});

function getKey(header, callback) {
  client.getSigningKey(header.kid, (err, key) => {
    if (err) {
      return callback(err);
    }
    const signingKey = key.getPublicKey();
    callback(null, signingKey);
  });
}

const token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImtleS1pZC0xIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; // Reemplaza con tu token

jwt.verify(token, getKey, { algorithms: ["RS256"] }, (err, decoded) => {
  if (err) {
    console.error("Error al verificar el token:", err);
  } else {
    console.log("Token verificado:", decoded);
  }
});

PHP (ejemplo general)

Este ejemplo ilustra los pasos generales para verificar un JWT RS256 en PHP. Necesitarás una librería de terceros para el manejo de JWKS y la verificación de firmas.

<?php
  $jwks_uri = 'https://tu-idp.com/.well-known/jwks.json';
  $token = 'eyJhbGciOiJSUzI1NiIsImtpZCI6ImtleS1pZC0xIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'; // Reemplaza con tu token

  // Obtener JWKS (requiere una librería que soporte JWKS)
  $jwks_json = file_get_contents($jwks_uri);
  $jwks = json_decode($jwks_json, true);

  // Seleccionar la clave por kid (requiere lógica personalizada)
  $header = json_decode(base64_decode(explode('.', $token)[0]), true);
  $kid = $header['kid'];
  $key = null;
  foreach ($jwks['keys'] as $jwk) {
    if ($jwk['kid'] === $kid) {
      $key = $jwk;
      break;
    }
  }

  if (!$key) {
    die('Clave no encontrada en JWKS');
  }

  // Convertir JWK a formato utilizable por la librería de verificación (ej: PEM)

  // Verificar el token (requiere una librería de JWT)
  // Utiliza la clave pública convertida y verifica el algoritmo RS256
  // Verifica los claims (exp, nbf)
?>

Nota: En PHP, deberás usar una librería como firebase/php-jwt para realizar la verificación. La conversión de JWK a PEM también requiere una lógica adicional.

Checklist final para producción

Asegúrate de implementar estos puntos en tu entorno de producción:

  • Verificación del algoritmo: Confirma que el algoritmo del JWT sea RS256 (o los algoritmos permitidos en tu aplicación) para evitar ataques. Rechaza cualquier otro algoritmo.
  • Obtención del JWKS: Obtén el JWKS correcto desde la URL proporcionada por el IdP. Considera el uso de la configuración de OIDC para una mayor flexibilidad.
  • Selección por kid: Selecciona la clave pública correcta usando el valor de kid del header del JWT.
  • Validación de la firma: Verifica la firma del token con la clave pública seleccionada. Usa una librería de confianza y especifica RS256.
  • Validación de claims: Valida los claims exp, nbf e iat, aplicando un margen de tolerancia (clock skew).
  • Caché y rotación de claves: Cachea el JWKS con un TTL razonable (ej. 5-30 minutos). Implementa un mecanismo para manejar la rotación de claves de forma segura, como reintentar la obtención del JWKS si la verificación falla.
  • Logging y monitorización: Registra los errores de verificación (ej. firma inválida, token expirado) y monitoriza el rendimiento de la verificación.

Preguntas frecuentes

¿Es seguro confiar en el payload antes de verificar la firma?

No. Nunca confíes en el contenido del payload antes de verificar la firma. Decodificar el JWT antes de verificar la firma es útil para fines de diagnóstico, pero no debe usarse para tomar decisiones de autorización. La verificación de la firma garantiza la integridad y autenticidad del token.

¿Con qué frecuencia debo refrescar el JWKS?

Cachea el JWKS con un TTL (Time To Live) razonable. Un TTL de 5 a 30 minutos es una buena práctica. El objetivo es equilibrar la seguridad con el rendimiento. Un TTL más corto mejora la seguridad, pero podría afectar el rendimiento. Implementa un mecanismo para manejar la rotación de claves. Si la verificación falla, reintenta refrescando el JWKS.

¿Qué significa kid?

kid significa Key ID (Identificador de la Clave). Es un identificador que el IdP incluye en el header del JWT para indicar qué clave pública del JWKS se debe usar para verificar la firma del token. Permite la rotación de claves sin afectar a los tokens emitidos anteriormente.

¿Qué es el clock skew?

El clock skew es la diferencia de tiempo entre el servidor que verifica el JWT y el servidor que emitió el token. Debido a las diferencias de tiempo entre los servidores, debes aplicar un margen de tolerancia (clock skew) al validar los claims relacionados con el tiempo (exp y nbf). Esto evita falsos positivos (tokens rechazados prematuramente) y asegura que los tokens válidos sean aceptados, incluso si los relojes de los servidores no están perfectamente sincronizados.

Recomendación final

La verificación de JWT RS256 es una parte esencial de la seguridad de cualquier aplicación que utilice tokens para la autenticación y autorización. Sigue los pasos descritos en esta guía para implementar una verificación segura y eficiente. Recuerda que la seguridad es un proceso continuo; mantente actualizado con las últimas prácticas y amenazas de seguridad.

Autor: Equipo Tecno Inteligente
Especialistas en automatización, desarrollo web y herramientas digitales.

Artículos recomendados