JWT

2 tools

Fundamentos de seguridad web

La seguridad web es la práctica de proteger aplicaciones web y APIs del acceso no autorizado, las brechas de datos y los ataques. Las aplicaciones modernas usan autenticación, autorización y criptografía para hacer cumplir los límites de seguridad.

Los JSON Web Tokens (JWT) son el mecanismo de autenticación sin estado dominante en el desarrollo web moderno. Entender cómo funcionan los JWT — incluyendo su estructura, algoritmos de firma y vulnerabilidades — es esencial para construir APIs y aplicaciones seguras.

JSON Web Tokens (JWT)

Un JWT es una forma compacta y segura para URLs de representar afirmaciones entre dos partes. Consta de tres partes codificadas en Base64url separadas por puntos. Los JWT pueden verificarse sin consultas a bases de datos porque la firma cubre todo el token.

Las tres partes de un JWT

Header

Contiene metadatos sobre el token: el algoritmo de firma (alg) y el tipo de token (typ). Siempre JSON codificado en Base64url. La elección del algoritmo aquí afecta la seguridad de todo el token.

Codificado
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Decodificado
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload

Contiene las afirmaciones: declaraciones sobre el usuario y metadatos adicionales. También JSON codificado en Base64url. Cualquiera puede decodificar esto — los datos del payload NO están cifrados, solo firmados.

Codificado
eyJzdWIiOiJ1c2VyXzEyMyIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzIwMDAwMH0
Decodificado
{
  "sub": "user_123",
  "role": "admin",
  "exp": 1717200000
}
Signature

Una firma criptográfica sobre el encabezado y el payload codificados. Verificar esta firma garantiza que el token no fue alterado. La clave secreta (HMAC) o la clave privada (RSA/ECDSA) nunca se incluye en el token.

Codificado
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Decodificado
HMACSHA256(
  base64url(header) + "." +
  base64url(payload),
  secret
)

Afirmaciones JWT estándar

La especificación JWT define nombres de afirmaciones estándar. Usarlos garantiza la interoperabilidad entre diferentes bibliotecas y servicios JWT:

AfirmaciónNombreDescripción
issIssuerIdentifica al principal que emitió el token (ej. URL de tu servidor de autenticación)
subSubjectIdentifica al principal que es el sujeto del token (ej. ID de usuario)
audAudienceIdentifica a los destinatarios para los que está destinado el token (ej. URL de tu API)
expExpirationTimestamp Unix después del cual el token no debe aceptarse para su procesamiento
nbfNot BeforeTimestamp Unix antes del cual el token no debe aceptarse para su procesamiento
iatIssued AtTimestamp Unix en el que se emitió el token — usado para determinar su antigüedad
jtiJWT IDIdentificador único para el token, usado para prevenir ataques de repetición de tokens

Algoritmos de firma

El algoritmo de firma se declara en el encabezado JWT. Elegir el algoritmo correcto para tu caso de uso es crítico para la seguridad:

HS256 / HS384 / HS512Simétrico (HMAC)

Usa una clave secreta compartida para firmar y verificar. Simple de implementar pero requiere que todos los verificadores conozcan el secreto.

Usar cuando: Servicios internos donde controlas todas las partes. Nunca usar cuando terceros necesitan verificar tokens.
RS256 / RS384 / RS512Asimétrico (RSA)

Usa una clave privada para firmar y una clave pública para verificar. La clave privada nunca sale del servidor de autenticación.

Usar cuando: Arquitecturas de microservicios, verificación de tokens de terceros, OAuth2 y OpenID Connect.
ES256 / ES384 / ES512Asimétrico (ECDSA)

Como RSA pero con claves más pequeñas y firma más rápida. Proporciona seguridad equivalente con mejor rendimiento.

Usar cuando: Aplicaciones móviles y IoT donde el rendimiento importa. Alternativa moderna a RSA.
"alg": "none"Sin firmar — PELIGROSO

Sin firma alguna. Un token con alg:none no tiene garantía de integridad y puede ser falsificado por cualquiera.

Usar cuando: Nunca usar en producción. Algunas bibliotecas JWT históricamente aceptaban alg:none, lo que condujo a vulnerabilidades críticas.

Flujos de autenticación

Concesión de contraseña (directa)
  1. 1.El usuario envía nombre de usuario y contraseña al endpoint de inicio de sesión
  2. 2.El servidor valida las credenciales contra la base de datos de usuarios
  3. 3.El servidor firma un JWT con las afirmaciones del usuario y la expiración
  4. 4.El cliente almacena el JWT (localStorage, cookie o memoria)
  5. 5.El cliente envía el JWT en el encabezado Authorization: Bearer para las solicitudes posteriores
Código de autorización + PKCE (OAuth2)
  1. 1.El cliente redirige al usuario al servidor de autorización con el desafío de código
  2. 2.El usuario se autentica y autoriza la aplicación cliente
  3. 3.El servidor de autenticación redirige de vuelta con un código de autorización de un solo uso
  4. 4.El cliente intercambia el código + verificador por tokens de acceso y actualización
  5. 5.El cliente usa el token de acceso para llamadas a la API; el token de actualización para renovación

Vulnerabilidades JWT comunes

Los JWT son seguros cuando se implementan correctamente. Estos son los errores de implementación más comunes que conducen a vulnerabilidades de seguridad:

Confusión de algoritmo (alg:none)Crítico

Algunas bibliotecas aceptan tokens con alg:none (sin firma). Un atacante puede modificar el payload y establecer alg en none para falsificar cualquier JWT. Siempre especifica y valida explícitamente el algoritmo permitido.

Confusión HS256 / RS256Crítico

Si una biblioteca espera verificar RS256 pero acepta HS256, un atacante puede firmar un token usando la clave pública como secreto HMAC. Siempre fija el algoritmo esperado.

Validación de expiración ausenteAlto

Un JWT sin reclamación exp, o código que no verifica exp, permite que los tokens se usen indefinidamente. Siempre establece tiempos de expiración cortos y valida la reclamación exp.

Datos sensibles en el payloadAlto

Los payloads JWT están codificados en Base64, no cifrados. Nunca almacenes contraseñas, números de tarjetas de crédito u otros secretos en las afirmaciones JWT.

Claves secretas débiles (HS256)Medio

Los JWT firmados con HMAC con secretos cortos o predecibles pueden ser forzados brutos sin conexión. Usa secretos aleatorios criptográficamente de al menos 256 bits.

Verificación de firma ausenteMedio

Aceptar JWTs sin verificar la firma confía completamente en el payload. Siempre verifica la firma antes de confiar en cualquier afirmación.

Preguntas frecuentes

¿Están cifrados los JWT?

Los JWT estándar (JWS) están firmados pero NO cifrados. El payload está codificado en Base64url, que es trivialmente reversible. JWE (JSON Web Encryption) proporciona cifrado pero es mucho menos común.

¿Cuánto tiempo debe ser válido un JWT?

Los tokens de acceso deben ser de corta duración: de 5 a 60 minutos es típico. Usa tokens de actualización (de mayor duración, almacenados de forma segura) para obtener nuevos tokens de acceso.

¿Dónde debo almacenar los JWT en el navegador?

Las cookies HttpOnly son la opción más segura — son inaccesibles para JavaScript, previniendo el robo por XSS. localStorage es vulnerable a XSS pero evita CSRF. No hay opción perfecta.

¿Puedo revocar un JWT antes de que expire?

No sin estado del lado del servidor. Soluciones: tiempos de expiración cortos, una lista de bloqueo de tokens (Redis) o tokens de sesión opacos para operaciones sensibles.

¿Cuál es la diferencia entre JWT y cookies de sesión?

Las cookies de sesión almacenan un ID de sesión aleatorio; el servidor busca los datos de sesión. Los JWT son autónomos — el servidor valida la firma sin una consulta a la base de datos.

¿Qué afirmaciones debo incluir en un JWT?

El mínimo: sub (ID de usuario), exp (expiración) e iat (emitido en). Agrega iss (emisor) para configuraciones multi-servicio. Mantén los payloads pequeños.

¿Es RS256 mejor que HS256?

RS256 (asimétrico) es mejor para la mayoría de los sistemas de producción porque solo el servidor de autenticación necesita la clave privada. Múltiples servicios pueden verificar tokens usando la clave pública.

¿Qué es PKCE y por qué es importante?

PKCE (Proof Key for Code Exchange) es una extensión del flujo de código de autorización OAuth2 que previene los ataques de interceptación de código de autorización. Es obligatorio para clientes públicos (SPAs, aplicaciones móviles).