Glosario

¿Qué es un JWT (JSON Web Token)? Cómo funcionan los tokens firmados y cómo usarlos de forma segura

Un JWT es un token firmado por un servidor para detectar manipulaciones. Cómo funciona y cómo usarlo bien: verificar la firma, rechazar alg:none y expirar.

Publicado 2026-06-12 Actualizado 2026-10-06 9 min de lectura
En esta página

Un token firmado que un servidor te entrega tras iniciar sesión: eso es un JWT. Aquí tienes cómo funciona y los puntos clave para usarlo de forma segura (sin pasos de ataque).

Cómo funciona (tres partes)

Un JWT es encabezado.carga_útil.firma unido con .. El encabezado y la carga útil están solo codificados en base64url (no cifrados); únicamente la firma se hace con una clave secreta (o compartida).

1. encabezado

metadatos como el algoritmo de firma. cualquiera puede leerlo

2. carga útil

claims como el id de usuario y la expiración. cualquiera puede leer = sin secretos

3. firma

hecha con una clave. garantiza que no hay manipulación

Un JWT tiene tres partes. El encabezado y la carga útil son 'solo legibles'; la firma aporta la garantía de autenticidad.

El punto clave es que el contenido es "solo legible". Así que la carga útil no es lugar para contraseñas ni datos personales. El valor de un JWT es que, al verificar la firma, el servidor puede confirmar "yo emití este token y no ha sido alterado".

Defensas para usarlo de forma segura

1

Verifica siempre la firma y fija el alg (lo más importante)

Verifica la firma en el servidor cada vez. Fija el algoritmo de firma (alg) aceptado al valor que esperas y rechaza alg:none (sin firma). No confíes a ciegas en el alg escrito en el encabezado del token.

El RFC de buenas prácticas de JWT (RFC 8725) establece que las bibliotecas DEBEN permitir a quien las llama especificar un conjunto de algoritmos admitidos y NO DEBEN usar ningún otro, y que todas las operaciones criptográficas del JWT deben validarse, rechazando el JWT entero si alguna falla.

2

Bloquea el cambio de algoritmo, no solo alg:none

Abusar de alg no consiste solo en quitar la firma. El RFC 8725 describe cómo, al cambiar RS256 por HS256, algunas bibliotecas intentan validar la firma con HMAC-SHA256 usando la clave pública RSA como secreto compartido (confusión de algoritmos). La clave pública es, por definición, pública: si eso funciona, un atacante puede crear él mismo una firma válida.

La defensa es la misma: no confíes en el alg del encabezado; fija el algoritmo que espera el servidor. Decide primero el algoritmo y luego verifica, en lugar de elegir la rutina de verificación según el material de clave que te entregan.

3

Valida para quién es y hasta cuándo

Una firma válida solo te dice que el token es genuino. Si es para ti y sigue vigente es una comprobación aparte.

El RFC 7519 establece que, para aud, si quien procesa el claim no se identifica con un valor del claim «aud» cuando este está presente, el JWT DEBE rechazarse, y que exp identifica el momento de expiración a partir del cual el JWT NO DEBE aceptarse para su procesamiento (nbf funciona igual en el otro extremo). El RFC 8725 añade que la aplicación debe validar que las claves usadas pertenecen al emisor. Que tu servicio acepte un token emitido legítimamente para otro servicio es justo lo que ocurre si te saltas estas comprobaciones.

4

No pongas secretos en la carga útil

Asume que cualquiera puede decodificar el contenido. Mantén los secretos —contraseñas, datos personales, claves de API— fuera de él. Incluye solo claims que no sean catastróficos si se ven, como identificadores y permisos.

5

Mantén la expiración corta y ten forma de revocar

Haz que los tokens de acceso sean de vida corta. Una expiración demasiado larga alarga la ventana de daño si uno es robado. Si necesitas revocación, combina un token de acceso de vida corta con un refresh/sesión gestionado en el servidor.

6

Usa una clave fuerte y guárdala donde no puedan robarla

Haz la clave de firma fuerte, no la reutilices y guárdala en un lugar seguro del servidor. Protege también el token en sí: evita que sea robado vía XSS, llévalo en una cookie con atributos seguros (→ cuidado con el robo vía XSS).

La opinión de este sitio: un JWT no es un mecanismo de sesión para cualquier uso

Los JWT se usan a menudo para "mantener el estado de inicio de sesión", pero tienen una debilidad: la revocación es difícil. Si la firma es válida y no ha expirado, el servidor básicamente confía en él, así que hacer que un cierre de sesión o una invalidación surta efecto de inmediato resulta incómodo.

Nuestra postura es: no uses un JWT como sustituto de larga duración de una sesión. Combina un token de acceso de vida corta con un refresh/sesión revocable en el servidor, y obtienes tanto la ventaja del JWT (verificación barata) como una revocación fácil.

Cuidado: "se decodificó" no es "es válido"

Como el contenido es legible, cualquiera puede pegar un JWT en un decodificador de JWT e inspeccionar el encabezado y la carga útil. Pero decodificar (leer el contenido) y verificar (confirmar la autenticidad) son cosas completamente distintas.

Poder decodificar no garantiza nada sobre la validez. Lo que decide si un token es genuino es siempre la verificación de la firma en el servidor. Leer el contenido para depurar es práctico: solo no confundas "pude leerlo" con "es válido".

JWT frente a sesiones en el servidor (cookies)

Un JWT es solo una forma de mantener el estado de inicio de sesión, y en unos casos encaja mejor que una sesión en el servidor y en otros peor.

AspectoSesión en el servidor (cookie)JWT
Dónde vive el estadoEn el servidor (BD o memoria); la cookie solo lleva un IDDentro del token; el servidor solo verifica la firma
Cierre de sesión / suspensiónBorrarla en el servidor surte efecto de inmediatoSe acepta hasta que expira, salvo que construyas la revocación aparte
Visibilidad del contenidoSolo un ID, nada que leerCualquiera puede decodificarlo y leerlo
Cuándo encajaUna aplicación web normal en un solo dominioVarios servicios o API que verifican el mismo token

Para una aplicación web que vive en un solo dominio, una sesión en el servidor suele bastar. Si eliges JWT, emitir un token nuevo al iniciar sesión sigue el mismo principio que la defensa contra la fijación de sesión.

Un caso real: una biblioteca que no comprobaba el algoritmo

El cambio de algoritmo no es solo teoría. La biblioteca de JWT para Node.js jsonwebtoken, muy usada, en sus versiones 4.2.1 y anteriores no comprobaba correctamente el algoritmo indicado en el encabezado del token, lo que permitía saltarse la verificación (CVE-2015-9235, corregido en 4.2.2). Un token que debía verificarse con una clave pública podía firmarse con un algoritmo de clave compartida (familia HS) y aun así pasar: exactamente la confusión de algoritmos descrita arriba.

Dos lecciones:

  • Mantén la biblioteca actualizada. Puedes revisar tus dependencias en busca de vulnerabilidades conocidas pegando un archivo de bloqueo (lockfile) en el escáner de vulnerabilidades de dependencias
  • No dependas de los valores por defecto de la biblioteca; indica el algoritmo aceptado de forma explícita en tu propio código

Cómo revisar tus propios tokens

Pega un token emitido por tu propio servicio en el decodificador de JWT y revisa lo siguiente. La decodificación se hace en tu navegador y el token no se envía a ningún servidor. Aun así, con un token real de producción conviene cerrar sesión después para invalidarlo.

  1. ¿El alg del encabezado es el que esperas (y no none)?
  2. ¿Hay un exp, y la duración desde iat (momento de emisión) es adecuada para el uso?
  3. ¿Están aud e iss presentes y apuntan a tu servicio?
  4. ¿Contiene la carga útil algo que no querrías que se viera: direcciones de correo, números de teléfono, claves de API?

Comprueba la verificación en el servidor con pruebas en un entorno de desarrollo. Un token con un carácter de la firma cambiado, un token con otro alg, un token expirado y un token destinado a otro servicio (aud incorrecto) deben rechazarse todos: mantenlo como prueba automatizada.

Fuentes (primarias)

  • IETF RFC 8725, «JSON Web Token Best Current Practices» (en inglés) — datatracker.ietf.org (fijar los algoritmos, validar cada operación criptográfica, confusión de algoritmos, claves que pertenecen al emisor)
  • IETF RFC 7519, «JSON Web Token (JWT)» (en inglés) — datatracker.ietf.org (las definiciones normativas de exp, nbf y aud)
  • GitHub Advisory Database, «Verification Bypass in jsonwebtoken» (CVE-2015-9235, en inglés) — github.com/advisories (afecta a 4.2.1 y anteriores; corregido en 4.2.2)
  • OWASP HTML5 Security Cheat Sheet (en inglés) — cheatsheetseries.owasp.org (no guardar identificadores de sesión en localStorage)

Sigue leyendo

FAQ

Q¿El contenido de un JWT está cifrado?
A

No. El encabezado y la carga útil de un JWT estándar están 'codificados' con base64url, no cifrados, así que cualquiera que tenga el token puede leer el contenido. Por eso nunca pongas secretos como contraseñas o datos personales en la carga útil. Lo que protege un JWT no es la 'confidencialidad del contenido' sino 'que no haya sido manipulado' (la integridad, vía la firma).

Q¿Cuál es el ajuste más peligroso de un JWT?
A

No verificar la firma, o aceptar 'alg:none' (sin firma). Permitir eso deja que un atacante pase un token falsificado con el contenido reescrito libremente. La defensa es verificar siempre la firma en el servidor y fijar el algoritmo de firma (alg) aceptado al valor que esperas.

Q¿Decodificar y verificar son lo mismo?
A

No. Decodificar solo lee el contenido y cualquiera puede hacerlo (puedes comprobarlo con un decodificador de JWT). Verificar es que el servidor confirme, con una clave secreta/pública, que la firma es válida, que el token no ha expirado y que el emisor/audiencia son correctos. 'Se decodificó' no significa 'es un token válido': la verificación en el servidor decide la autenticidad.

Q¿Uso JWT o sesiones (cookies)?
A

Para una aplicación web normal en un solo dominio, una sesión en el servidor con una cookie suele bastar, y el cierre de sesión o la suspensión de una cuenta surten efecto de inmediato. Los JWT encajan cuando varios servicios o API verifican el mismo token, o cuando recibes tokens de un proveedor de identidad externo (OAuth/OpenID Connect). Si usas JWT, mantén la expiración corta y combínalos con algo que el servidor pueda revocar.

Q¿Puedo guardar un JWT en localStorage?
A

No se recomienda. JavaScript siempre puede leer localStorage, así que un solo fallo XSS permite a un atacante robar el token. OWASP también desaconseja guardar identificadores de sesión en localStorage. En el navegador es más seguro llevar el token en una cookie con HttpOnly, Secure y SameSite; si usas una cookie, añade también protección contra CSRF.

Q¿Qué es 'alg:none' en un JWT?
A

Es un JWT cuyo encabezado pone alg (el algoritmo de firma) a none, es decir, sin firma. La especificación lo permite, pero un token usado para autenticación, como el inicio de sesión, nunca debe aceptarlo; de lo contrario, cualquiera puede crear un token con el contenido reescrito. Evítalo fijando en el servidor el algoritmo aceptado al valor que esperas (por ejemplo, solo RS256).