Elffuss Elffuss CodeProyecto del día
Proyecto del día · 17 de septiembre de 2026

«Caduca el 1 de enero de 1970»: el decodificador de JWT de una tarde

Una utilidad de cuarenta líneas para leer tokens sin pegarlos en una web ajena. El split por puntos fue lo fácil; los acentos y el 1970, no.

El IDE con IA local en el navegadorlocal · en el navegador

La queja era de las vagas: «a Marta se le cierra la sesión antes de tiempo». Para saber qué llevaba dentro el token había que decodificarlo, y el reflejo de todo el mundo es abrir la primera web de decodificar JWT que sale en Google y pegar. Un token de producción. O sea, la sesión viva de una persona real.

El plan: cuarenta líneas

La utilidad de la tarde: pegas el token, te enseña cabecera y payload formateados, y traduce exp, iat y nbf a fechas que se entiendan. La primera versión salió del editor en dos intentos: partir por el punto, cambiar - y _ por + y /, rellenar el padding, atob, JSON.parse. Formalmente correcto. Y entonces pegué un token de verdad.

El apellido salía como «Martínez». atob no devuelve texto, devuelve bytes disfrazados de cadena: con ASCII cuela, con una tilde no. Se lo dije tal cual —«los acentos salen partidos»— y metió el paso que faltaba, de la cadena binaria a un Uint8Array y de ahí a TextDecoder. Es una línea que solo se te ocurre cuando has visto el destrozo en pantalla.

El segundo fallo fue más divertido: la caducidad ponía 1 de enero de 1970. Todas. exp viene en segundos y new Date() quiere milisegundos. Multiplicar por mil y arreglado, pero hasta que no lees esa fecha absurda no caes en que el token no tenía nada raro; el raro era mi visor.

Lo que no hace, dicho en la propia pantalla

Aquí sí hubo que frenar al modelo, que se venía arriba con la palabra «validar». Decodificar no es verificar: cualquiera puede fabricarse un payload y firmarlo con alg: none. La utilidad solo lee, y no debe aparentar otra cosa, así que el aviso está en la interfaz y no en un comentario del código. Un compañero con prisa no lee comentarios.

Aquí el dato de prueba no es un dato: es una llave.

Y por eso esto se escribe con el modelo dentro del navegador. Un CSV pegado en una web ajena es, como mucho, una indiscreción. Un JWT es una credencial en activo: quien lo tenga se hace pasar por esa persona hasta que caduque. Pegarlo en un formulario de terceros —por muy respetable que sea el tercero— es regalarlo, y de paso dejarlo en el historial del navegador y en los registros de alguien. Con el modelo corriendo en la pestaña, el token entra en el editor, se decodifica y se queda ahí. No hay petición que interceptar porque no hay petición.

La cosa son ochenta líneas y un textarea. Pero es lo que uso a diario, y ya no tengo que pararme a pensar de dónde ha salido el token antes de pegarlo.

Ábrelo en Elffuss Code y escríbete el tuyo: el modelo corre dentro del navegador, sobre tu propia GPU, y ni el token ni el código que le enseñas salen de la pestaña.

Abrir Code →
nada de esto se sube a ningún sitio