Como decodificar un JWT: guia completa sobre JSON Web Tokens para desarrolladores
Aprende que es un JWT, como decodificarlo, su estructura (header, payload, signature), cuando usarlo y errores de seguridad comunes.
Que es un JWT y para que sirve
Un JWT (JSON Web Token, pronunciado "jot") es un estandar abierto (RFC 7519) para transmitir informacion de forma compacta y verificable entre dos partes como un objeto JSON firmado digitalmente.
Casos de uso principales:
- Autenticacion: Despues del login, el servidor genera un JWT que el cliente envia en cada request. El servidor verifica la firma sin necesidad de consultar la base de datos.
- Autorizacion: El JWT contiene roles/permisos del usuario. El servidor lee el payload sin round-trip a la DB.
- Intercambio de informacion: Datos firmados entre microservicios. El receptor verifica que los datos no fueron alterados.
Quien usa JWT: Auth0, Firebase, AWS Cognito, Supabase, la mayoria de APIs REST modernas, OAuth 2.0/OpenID Connect.
Decodifica cualquier JWT al instante con el decodificador JWT de NexTools.
Estructura de un JWT: las 3 partes
Un JWT tiene 3 partes separadas por puntos: xxxxx.yyyyy.zzzzz
1. Header (encabezado): Indica el algoritmo de firma y tipo de token.
{"alg": "HS256", "typ": "JWT"} → codificado en Base64url.
2. Payload (carga util): Contiene los "claims" — datos del usuario y metadatos.
{"sub": "1234567890", "name": "Juan", "admin": true, "iat": 1773705600, "exp": 1773792000}
Claims estandar:
iss(issuer): quien emitio el tokensub(subject): a quien perteneceexp(expiration): cuando expira (timestamp Unix)iat(issued at): cuando se creoaud(audience): para quien esta destinado
3. Signature (firma): Garantiza que el token no fue alterado.
HMACSHA256(base64url(header) + "." + base64url(payload), secret)
Si necesitas entender Base64, consulta nuestra guia sobre Base64 y codificacion.
Como decodificar un JWT paso a paso
Opcion 1: NexTools (la mas rapida). Pega tu JWT en el decodificador JWT de NexTools y ve instantaneamente header, payload y firma decodificados. Todo en tu navegador — el token no sale de tu computadora.
Opcion 2: Terminal.
echo "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.xxx" | cut -d. -f2 | base64 -d
Opcion 3: JavaScript.
const payload = JSON.parse(atob(token.split('.')[1]));
console.log(payload);
IMPORTANTE: Decodificar ≠ verificar. Cualquiera puede decodificar un JWT (es Base64). VERIFICAR requiere la clave secreta para confirmar que la firma es valida. Nunca confies en un JWT sin verificar la firma.
JWT vs sesiones vs cookies: cuando usar cada uno
| Mecanismo | Estado | Almacenamiento | Escalabilidad | Mejor para |
|---|---|---|---|---|
| JWT | Stateless | Cliente (localStorage/cookie) | Excelente (no DB lookup) | APIs, microservicios, SPAs |
| Sesion | Stateful | Servidor (Redis/DB) | Requiere session store compartido | Apps monoliticas, SSR |
| Cookie | Ambos | Navegador (enviada auto) | Depende del contenido | Transporte de session ID o JWT |
Recomendacion 2026: Para APIs publicas y microservicios: JWT. Para apps web con SSR (Next.js): sesiones server-side o JWT en httpOnly cookies. Para apps simples: sesiones + cookies.
Errores de seguridad comunes con JWT
1. Guardar JWT en localStorage. Vulnerable a XSS. Un script malicioso puede leer localStorage y robar el token. Mejor: httpOnly cookie (no accesible desde JavaScript).
2. No verificar la firma. Decodificar el payload sin verificar la firma permite que un atacante modifique los claims (ej: cambiar "admin": false a "admin": true).
3. Algoritmo "none". Algunos JWT permiten "alg": "none" (sin firma). Si tu servidor lo acepta, cualquiera puede crear tokens falsos. Siempre valida que el algoritmo sea el esperado.
4. Secret debil. Si usas HS256, el secreto debe ser largo (256+ bits) y aleatorio. "my-secret-key" se rompe por fuerza bruta en minutos. Genera claves seguras con el generador de contrasenas de NexTools.
5. Tokens sin expiracion. Un JWT sin exp es valido para siempre. Si se filtra, el atacante tiene acceso permanente. Siempre pon expiracion (15 min - 1 hora para access tokens).
Access tokens vs refresh tokens: la estrategia correcta
Access token: JWT de vida corta (15 min - 1 hora). Se envia en cada request API. Si se compromete, el dano es limitado por la expiracion.
Refresh token: Token de vida larga (7-30 dias). Se usa SOLO para obtener un nuevo access token cuando el actual expira. Se almacena de forma mas segura (httpOnly cookie, server-side).
Flujo:
- Login → servidor emite access token (15 min) + refresh token (7 dias)
- Cliente usa access token para requests API
- Access token expira → cliente usa refresh token para obtener nuevo access token
- Refresh token expira → usuario debe hacer login de nuevo
Si necesitas entender los hashes que protegen los tokens, consulta nuestra guia sobre hashes MD5 y SHA-256.
JWT en diferentes lenguajes y frameworks
Node.js (jsonwebtoken):
const jwt = require('jsonwebtoken');
const token = jwt.sign({ userId: 123 }, 'secret', { expiresIn: '1h' });
const decoded = jwt.verify(token, 'secret');
Python (PyJWT):
import jwt
token = jwt.encode({"userId": 123}, "secret", algorithm="HS256")
decoded = jwt.decode(token, "secret", algorithms=["HS256"])
Next.js / Auth.js: Usa JWT como session strategy por defecto. Configurable en authOptions.
Spring Boot: Spring Security + jjwt library para JWT authentication filter.
Depurar JWT: herramientas y tips
NexTools: El decodificador JWT muestra header, payload y firma con formato legible. Resalta si el token esta expirado.
jwt.io: El debugger mas conocido. Permite verificar firma pegando el secreto. CUIDADO: no pegues tokens de produccion en sitios de terceros.
Chrome DevTools: Application tab → Cookies/Storage → encuentra el JWT y decodifica manualmente o con extension.
Tips de debugging:
- Si recibes 401 Unauthorized: verifica que el token no este expirado (
expvs fecha actual) - Si los claims no coinciden: verifica que el payload tenga los campos esperados por tu servidor
- Si la firma falla: verifica que el secreto/clave publica sea correcto en el servidor que verifica
Convierte timestamps exp e iat a fechas legibles con el conversor de timestamps de NexTools.
Prueba esta herramienta:
Abrir herramienta→Preguntas frecuentes
Un JWT esta cifrado o solo codificado
Un JWT estandar (JWS) esta CODIFICADO en Base64url, no cifrado. Cualquiera puede leer el payload sin la clave secreta. Para JWT cifrados existe JWE (JSON Web Encryption), que si protege el contenido, pero es menos comun. NUNCA pongas datos sensibles (contrasenas, tarjetas de credito) en un JWS.
Donde debo guardar el JWT en el cliente
La opcion mas segura es una httpOnly cookie con flags Secure y SameSite=Strict. Esto previene XSS (JavaScript no puede leerla) y CSRF (SameSite). localStorage es vulnerable a XSS. sessionStorage se pierde al cerrar la pestana.
Como invalido un JWT antes de que expire
Es el problema principal de JWT: no puedes invalidarlos directamente (son stateless). Opciones: (1) lista negra en Redis/DB del token revocado, (2) tokens de vida corta + refresh tokens, (3) cambiar el secreto de firma (invalida TODOS los tokens). Las sesiones server-side no tienen este problema.
HS256 vs RS256: que algoritmo de firma usar
HS256 (simetrico): una sola clave secreta para firmar y verificar. Mas simple. Ideal cuando el mismo servicio firma y verifica. RS256 (asimetrico): clave privada firma, clave publica verifica. Ideal cuando un servicio firma y OTROS verifican (microservicios, OAuth).
Los JWT son seguros para autenticacion
Si, si se implementan correctamente: httpOnly cookies, tokens de vida corta, refresh token rotation, verificacion de firma, algoritmo correcto, secreto fuerte. Mal implementados (localStorage, sin expiracion, secreto debil), son inseguros.
Puedo poner lo que quiera en el payload del JWT
Tecnicamente si, pero no deberias poner datos sensibles (el payload es legible sin clave). El payload ideal contiene: user ID, roles, expiracion, y metadata necesaria para la autorizacion. No passwords, PII innecesaria, ni datos grandes.