Mensaje de error
"nbf" claim timestamp check failed
jose (JavaScript) — JWTClaimValidationFailed, code ERR_JWT_CLAIM_VALIDATION_FAILED
Qué significa
El token lleva un claim `nbf` («no antes de») que, según el reloj del verificador, todavía está en el futuro, así que jose lo rechaza por no ser aún válido. La firma y los demás claims (declaraciones) pueden estar perfectamente bien: el error se refiere solo al tiempo. Casi siempre significa que los relojes del emisor y del verificador difieren en más de la tolerancia que permites (cero por defecto).
Por qué ocurre
El reloj del verificador va retrasado respecto al del emisor
frecuenteMuchos emisores fijan `nbf` en el momento de emisión. Si el reloj del host que verifica se retrasa aunque sea unos segundos, cada token recién emitido es «del futuro» durante ese tiempo. Los contenedores y las VM heredan el reloj del host, así que un solo host cuyo reloj se desvía rompe a la vez todos los servicios que aloja.
Token usado en el mismo momento de su emisión, sin tolerancia
frecuenteLas pruebas y las llamadas entre servicios suelen emitir un token y enviarlo en cuestión de milisegundos. Con `clockTolerance` en su valor predeterminado de 0 segundos, el desfase normal entre dos máquinas basta para provocar fallos intermitentes.
El emisor fijó nbf en el futuro a propósito
ocasionalAlgunos sistemas emiten por adelantado tokens que pasan a ser válidos más tarde (tareas programadas, enlaces diferidos). Si se usa uno de esos tokens antes de tiempo, el rechazo es correcto: quien llama debe esperar hasta `nbf`.
nbf escrito en milisegundos
raraLos tiempos de un JWT se expresan en segundos desde la época Unix (RFC 7519, NumericDate). Un emisor que escribe `Date.now()` produce un `nbf` unos 50.000 años en el futuro, y el token nunca llega a ser válido.
Cómo solucionarlo
- 1.
Permitir un desfase de reloj pequeño y explícito
`clockTolerance` acepta segundos o una cadena de duración. De 30 a 60 segundos bastan para absorber la deriva real de los relojes; no es una forma de aceptar tokens con minutos de antelación.
js import { jwtVerify } from "jose"; const { payload } = await jwtVerify(token, jwks, { algorithms: ["ES256"], clockTolerance: "30s", // applies to nbf, exp and iat }); - 2.
Imprimir la cronología antes de cambiar la configuración
Compara `nbf` con la hora actual del verificador. Una diferencia de segundos apunta a un desfase; una de horas, a un error de zona horaria o de unidades en el emisor; un `nbf` de 13 dígitos, a milisegundos.
js import { decodeJwt } from "jose"; const { iat, nbf, exp } = decodeJwt(token); const now = Math.floor(Date.now() / 1000); console.log({ iat, nbf, exp, now, nbfInSeconds: nbf - now }); - 3.
Corregir el reloj que se desvía
Ejecuta NTP (chrony o systemd-timesyncd) en cada host que emita o verifique tokens. La tolerancia oculta los desfases pequeños; no debería tener que ocultar los grandes.
bash timedatectl status # "System clock synchronized: yes" chronyc tracking # offset from the NTP reference date -u +%s # compare with the token's nbf