Guías JWT

Cómo soluciono un JWT expirado correctamente

Confirmo si el JWT está realmente expirado, separo clock skew de expiration real y decido entre refresh, reauthentication o continuar con otras validaciones.

Por JWTDecoder.toolsÚltima verificación 2026-09-16

Voz editorial: la primera persona describe el flujo de trabajo documentado de JWTDecoder.tools; JWTDecoder.tools es el editor y autor organizacional.

exp → refresh / reauth → new JWT
exp → refresh / reauth → new JWT

Cuando una API dice token expired, jwt expired o devuelve invalid_token, primero confirmo si el JWT está realmente fuera de su ventana temporal. Distingo expiración real de clock skew, una política adicional del servidor o un 401 genérico que en realidad viene de firma, issuer o audience.

Empiezo con JWT Expiry Checker para leer exp, iat y nbf en UTC.

Paso 1: interpreto exp en segundos

JWT NumericDate usa segundos desde Unix epoch:

{
  "iat": 1789200000,
  "exp": 1789203600
}

En JavaScript:

const expiresAtMs = payload.exp * 1000;
const expired = Date.now() >= expiresAtMs;

Comparar directamente Date.now() con un exp de diez dígitos mezcla milisegundos y segundos.

Paso 2: comparo contra el reloj del verifier

La hora que importa es la del sistema que rechaza el token: API, gateway o middleware.

exp            12:00:00Z
API clock      12:00:06Z
clock leeway   5s
=> expired

Pocos segundos alrededor del límite pueden ser skew. Cuarenta minutos no.

Paso 3: reviso nbf, iat y reglas de edad máxima

Un token puede fallar aunque exp esté en el futuro porque:

  • nbf todavía no se alcanzó;
  • iat aparece anormalmente en el futuro;
  • la aplicación limita la edad máxima del token;
  • existe revocation/session policy adicional.

Por eso uso JWT Validator cuando necesito una decisión completa y no solo tiempo.

Paso 4: leo el error del servidor con contexto

RFC 6750 usa invalid_token para varios tipos de token inválido, no solo expiración. Busco mensajes como:

401 Unauthorized
invalid_token
TokenExpiredError
token expired
signature has expired
token not active

Si logs y timestamps coinciden, acepto la hipótesis de expiración. Si no, cambio de hipótesis.

Paso 5: elijo refresh o reauthentication

No edito exp. Cambiar el payload rompe la firma existente.

SituaciónAcción
Access Token expirado + refresh válidoobtener Access Token nuevo
refresh expirado/revocadoreauthentication
Client Credentialspedir un token nuevo al authorization server
no existe refresh flowejecutar de nuevo el flujo autorizado
exp sigue en futuroinvestigar otra validación

Race conditions durante refresh

Cuando varias requests detectan el token expirando al mismo tiempo, todas pueden intentar refresh. Si el sistema rota refresh tokens, una segunda request puede reutilizar un token ya consumido y provocar otra cadena de 401.

En clientes reales coordino el refresh, actualizo credenciales de forma atómica y evito que requests paralelas sigan usando el access token viejo.

Un token expirado puede tener firma válida

No hay contradicción:

signature valid   ✓
issuer valid      ✓
audience valid    ✓
expiration valid  ✕

La firma y la expiración responden preguntas distintas. Para aislar la primera uso JWT Signature Verifier.

Si falta exp

No todos los perfiles JWT hacen obligatorio exp. Reviso la especificación concreta y la política de la aplicación.

Para access tokens de vida corta, missing exp es una señal de policy que merece atención, pero no lo etiqueto automáticamente como JWT sintácticamente roto.

Qué reviso cuando parece expirar demasiado pronto

  1. sincronización de reloj de API/gateway;
  2. reloj del identity provider;
  3. seconds vs milliseconds;
  4. clock tolerance configurada;
  5. maximum token age;
  6. environment/token cache equivocado;
  7. revocation/session policy.

Una tolerancia grande no sustituye relojes correctos.

Mantengo separado refresh y validación

Un refresh token, una cookie de sesión o una nueva autenticación pueden recuperar una sesión, pero no cambian el significado del access token que ya expiró. Registro qué componente decidió rechazarlo y qué tiempos comparó, porque así evito confundir un problema de reloj, cache o revocación con una firma inválida.

Mi flujo de recuperación

  1. Abro JWT Expiry Checker.
  2. Confirmo exp, iat y nbf como NumericDate en segundos.
  3. Comparo exp con el clock del verifier real.
  4. Leo WWW-Authenticate y logs si están disponibles.
  5. Distingo expiración de otras causas de invalid_token.
  6. Si expiró, uso el flujo legítimo de refresh o reauthentication.
  7. No edito exp ni reutilizo una firma antigua.
  8. Si el token sigue activo, reviso firma, iss y aud con JWT Debugger.

La idea clave: expired no significa corrupto. Un JWT puede estar bien formado y correctamente firmado, pero ya fuera de su ventana de aceptación.

Fuentes y referencias

Guías relacionadas