JWT (JSON Web Token / jwt decoder / jwt online / decode jwt) no es cifrado, es codificacion — el payload usa base64url que decodifica a texto plano en un segundo, asi que nunca pongas contraseñas / PII / tarjetas bancarias / numeros de telefono en el payload JWT. Este articulo cubre 8 foot-guns reales de seguridad JWT + 5 escenarios de ataque de falsificacion + plan de proteccion 7 dias, que juntos evitan al menos 90% de las vulnerabilidades.

Resumen en 30 Segundos

  • JWT no es cifrado, es codificacion — muchos desarrolladores piensan que JWT es “seguro” porque la codificacion base64url parece ilegible, pero cualquiera puede decodificarlo en un segundo para obtener el payload en texto plano. JWT payload = texto plano, solo firmado, no cifrado
  • JWT estandar 4 riesgos principales: ataque alg=none / confusion de clave publica HS256 vs RS256 / exp no validado permite que tokens expirados pasen / eliminacion de firma algunas bibliotecas aceptan como fallback
  • Despliegue JWT 4 foot-guns: JWT secret hardcodeado en Git escaneado en horas / inyeccion de kid cualquier archivo usado como clave / sin blacklist tokens viejos validos despues del logout / expiracion larga (7 dias) cambio de contraseña no invalida tokens
  • 5 escenarios reales de ataque: filtracion de telefono en texto plano / falsificacion alg=none / firma HS256 con clave publica / exp no validado / eliminacion de firma pasa validacion
  • Plan de proteccion 7 dias (cada uno ≤ 30 minutos): forzar whitelist de algoritmo (siempre verificar exp) / JWT secret via env vars + .gitignore / validacion estricta de formato kid (whitelist de caracteres) / firma debe verificar (none rechazado) / expiracion corta (15 minutos) + rotacion de refresh token / blacklist + estado revoke en BD / nunca poner PII en payload JWT
  • Usa el Decodificador JWT Piick localmente para decodificar tokens sospechosos y verificar header / payload / exp / firma — 100% local sin subida, no contamina tu log de auditoria durante el debug

8 Foot-Guns Reales de JWT

Foot-Gun 1: JWT No Es Cifrado, Es Codificacion

Sintoma: Pones el numero de telefono / email / ultimos 4 digitos de tarjeta / hash de identificacion del usuario en el payload JWT, pensando “el token parece texto ilegible, otros no pueden leerlo”. Hasta que un dia el payload se filtra, base64url decodifica — telefono + email + hash de ID en texto plano todo expuesto, multa de cumplimiento GDPR desde ¥500k.

Por que: JWT tiene tres segmentos header.payload.signature, solo la firma esta firmada (HMAC/RSA firmada para evitar manipulacion), pero el payload en si es texto plano codificado con base64url. Cualquiera con el token (incluyendo logs de frontend / CDN / proxy inverso / DevTools del navegador) puede atob(token.split('.')[1]) decodificar a JSON en un segundo. JWT no es cifrado, es “texto plano a prueba de manipulacion”.

Arreglo:

  • Nunca pongas PII (Informacion de Identificacion Personal) en el payload JWT — sin telefono / email / tarjeta de identificacion / tarjeta bancaria / direccion / hash de contraseña
  • El payload JWT solo contiene “identificadores no sensibles” — user_id (UUID de base de datos, no numero derivable), role (rol, no estructura organizacional), exp / iat / nbf (timestamps)
  • Campos verdaderamente sensibles: ponlos en la base de datos del backend, el JWT solo tiene user_id, consulta DB cuando sea necesario
  • Si realmente necesitas datos sensibles en el token: usa JWE (JSON Web Encryption) — pero el 99% de los escenarios no lo necesitan

Escenario real: Una empresa SaaS puso numeros de telefono de usuarios directamente en el payload JWT (para “ahorrar una consulta a la base de datos”), 3 meses despues el JWT secret se filtro, 2 millones de telefonos de usuarios obtenidos a traves de decodificacion del payload en un clic, multas duales GDPR + Ley de Proteccion de Informacion Personal de China ¥8 millones.

Foot-Gun 2: Ataque alg=none

Sintoma: Tu biblioteca JWT es antigua (jwt-go version temprana / jsonwebtoken antes de 4.x / python-jose version vieja), un atacante construye header = {"alg": "none"} + payload arbitrario, falsifica un token admin, tu biblioteca del servidor acepta, el atacante obtiene directamente privilegios de admin.

Por que: El estandar JWT temprano RFC 7519 no exigia la validacion del lado del servidor del campo alg, algunas bibliotecas al ver alg: "none" confian directamente en el payload sin verificar la firma (porque “none” = “sin firma”, la biblioteca salta el paso de verificacion). Este es el ataque mas clasico en la historia de JWT, en 2015 Auth0 y otras bibliotecas multiples fueron afectadas.

Arreglo:

  • Forzar whitelist de algoritmo (siempre especifica algoritmos permitidos): jsonwebtoken.verify con whitelist de algoritmos: [‘HS256’]
  • Siempre rechazar alg: "none" (incluso si es compatible con RFC)
  • Actualizar a la ultima version de la biblioteca JWT (arregla vulnerabilidades conocidas de alg=none)
  • Revision de codigo verificando llamadas verify — sin parametro de algoritmos especificado es una vulnerabilidad

Escenario real: Reporte publico de Auth0 2015: biblioteca Node.js jsonwebtoken versiones antes de 4.2.2 aceptan alg: "none" por defecto, cualquier servidor que acepte tokens sin actualizar estaba bajo ataque. Despues del arreglo todas las bibliotecas modernas exigen especificar algoritmos.

Foot-Gun 3: Ataque de Confusion de Clave Publica HS256 vs RS256

Sintoma: Usas RS256 (RSA asimetrico), clave publica colocada en frontend / gateway para verificar tokens, pero algun desarrollador escribio la funcion verify, al ver header alg: "HS256" usa la misma clave publica como secret HMAC para verificar. El atacante obtiene la clave publica (ya es publica) → usa la clave publica como secret HMAC para firmar token HS256 → el servidor usa la misma clave publica para “verificar”, pasa → token admin falso evade autenticacion.

Por que: RS256 usa clave privada RSA para firmar, clave publica para verificar; HS256 usa el mismo secret tanto para firmar como para verificar. Si el codigo del servidor confunde “tengo una clave, usala”, el atacante puede usar cualquier tipo de clave para falsificar tokens. Esta es la vulnerabilidad mas clasica en el despliegue de RS256.

Arreglo:

  • Siempre forzar que el alg en el header coincida con el algoritmo configurado — algoritmo escrito en config (servicio RS256 siempre verifica alg=RS256 esperado)
  • secret / clave publica con nombres estrictamente separados (evitar confusion): const JWT_PRIVATE_KEY = …; // solo para firmar const JWT_PUBLIC_KEY = …; // solo para verificar
  • Revision de codigo verificando funcion verify — forzar lista de algoritmos verify (whitelist), no aceptar alg auto-reportado del token
  • Usa bibliotecas JWT maduras (PyJWT / jsonwebtoken / java-jwt) en lugar de implementar verify tu mismo

Escenario real: 2018 el servicio de gateway JWT de un banco uso RS256, pero la funcion verify tenia un bug de implementacion: jwt.verify(token, publicKey) no especificaba algoritmos, el atacante uso la clave publica como secret HMAC para firmar token HS256 pasando la verificacion, falsifico transferencia de $10 millones.

Foot-Gun 4: Campo exp No Validado o Validacion Filtrada

Sintoma: Tu JWT tiene campo exp (tiempo de expiracion), asumiendo validacion automatica, pero alguna ruta de codigo边缘 en el servidor solo verifica la firma no exp (por ejemplo, una ruta de fallback), los tokens expirados siguen siendo aceptados, la sesion nunca expira. El usuario cambia contraseña / es deshabilitado / cierra sesion, el token sigue siendo utilizable hasta que exp expire.

Por que: El estandar JWT RFC 7519 § 4.1.4 especifica que exp es MUST validate, pero muchas bibliotecas no fuerzan la validacion de exp por defecto (por compatibilidad con ciertos escenarios como “tokens permanentes”). Si la llamada verify no pasa explicitamente ignoreExpiration: false o verifica manualmente en codigo en lugar de usar la biblioteca, exp se omite.

Arreglo:

  • Siempre verificar exp explicitamente (no depender de valores por defecto): jwt.verify con algorithms: [‘HS256’] y ignoreExpiration: false
  • Tiempo de expiracion corto (access token 15 minutos, refresh token 7-30 dias)
  • reloj del servidor sincronizado con NTP (evitar desviacion del reloj que cause expiracion prematura / tardia del token)
  • El cliente no debe confiar en el tiempo local — usa Date.now() / time.time() y el tiempo del servidor para calcular la diferencia de exp

Escenario real: La expiracion del access token de un servicio SaaS era de 7 dias, un usuario cambio la contraseña pero el atacante uso el token viejo, pudo acceder a todos los recursos del usuario durante 7 dias. Acortar a 15 minutos + rotacion de refresh token es el estandar de la industria.

Foot-Gun 5: Filtracion de JWT Secret / Clave Privada Hardcodeado en Git

Sintoma: Escribes `const JWT_SECRET=*** en codigo + commit + push a GitHub (incluso repositorio privado, renuncia de empleado / robo de cuenta / filtracion interna). El secret scanning de GitHub escanea en 30 segundos, el JWT secret se filtra igual que las API keys, el atacante usa este secret para firmar tokens para cualquier usuario cualquier payload, todo el sistema comprometido.

Por que: El historial de Git nunca se borra (git filter-branch solo cambia el puntero de la rama, los objetos commit viejos permanecen en .git/objects/ durante 30 dias). El JWT secret es el mismo nivel de desastre que la API key despues de la filtracion — el atacante obtiene el secret = todo el sistema de autenticacion comprometido = identidad de usuario arbitrariamente falsificada.

Arreglo:

  • JWT secret via env vars + .gitignore: const JWT_SECRET=*** Nunca hardcodear en codigo
  • CI usa OIDC / tokens de corto plazo, sin secrets de largo plazo
  • JWT secret igual que rotacion + monitoreo de API key — el plan de proteccion de 7 dias de batch-24 api-key-leak-prevention aplica completamente

Escenario real: Una empresa fintech jwt-secret escrita en config/default.json comprometida a GitHub, el secret scanning de GitHub 30 segundos email + webhook al atacante, en 1 hora 2 millones de JWTs de usuarios re-firmados, saldos de usuarios arbitrariamente manipulados. Arreglo: mover secret a Vault / AWS Secrets Manager + CI OIDC.

Foot-Gun 6: Ataque de Inyeccion de kid (Key ID)

Sintoma: Usas arquitectura RS256 multi-clave, el campo kid en el header especifica que clave publica usar, el servidor getKey(header.kid) busca la tabla de claves publicas basado en kid. El atacante construye kid: "../../etc/passwd" o kid: "' OR 1=1--", algunas bibliotecas JWT directamente fs.readFileSync(getKey(kid)) o concatenan consulta SQL, causando lectura arbitraria de archivos / inyeccion SQL.

Por que: El campo kid esta pensado para ser “que clave usar para verificar”, pero las bibliotecas al implementar getKey a menudo tratan kid como nombre de archivo / parametro SQL / ruta URL, sin validacion de caracteres whitelist. El atacante usa kid para path traversal (LFI / RCE) o inyeccion SQL.

Arreglo:

  • kid whitelist estricto de caracteres (solo permitir [A-Za-z0-9_-]): validar kid con regex whitelist (alfanumerico + guion + guion bajo, 1-32 caracteres)
  • El valor kid debe estar en el conjunto de claves conocido (verificacion Map.has(kid))
  • No tratar kid como nombre de archivo / parametro SQL / ruta URL
  • Usa bibliotecas JWT maduras (implementar getKey tu mismo es facil que tenga bugs)

Escenario real: Node.js jsonwebtoken + algunos plugins soportan el campo jwk del header, el atacante construye jwk: [objecto con clave controlada por el atacante], hace que el servidor use la clave proporcionada por el atacante para verificar = definitivamente pasa. Arreglo: rechazar campos jwk / jku / x5u propios del token, solo usar la clave configurada en el servidor.

Foot-Gun 7: Ataque de Eliminacion de Firma

Sintoma: Cuando escribes la funcion verify, si alguna condicion limite (por ejemplo, header.alg no coincide con la whitelist) no se maneja, algunas bibliotecas caen en aceptar el token sin firma (header.payload. seguido de cadena vacia). El atacante modifica el payload (por ejemplo, cambia role a admin) → elimina la firma → alguna ruta de fallback salta la verificacion de firma → token falso pasa la validacion.

Por que: El formato JWT es header.payload.signature, si solo se pasa header.payload., la biblioteca analiza el segmento de firma como vacio, algunas implementaciones de bibliotecas if (!signature) return payload (porque “sin firma = no necesita verificar”), evade toda la verificacion de firma.

Arreglo:

  • Siempre verificar los 3 segmentos completos (header.payload.signature todos deben tener contenido)
  • Rechazar tokens con firma vacia (incluso si es compatible con RFC)
  • Siempre usar bibliotecas maduras (no dividir + verificar tu mismo)
  • Caso de prueba: construir header.payload. enviar, debe ser rechazado

Escenario real: Bug de implementacion de alguna biblioteca JWT: cuando la firma esta vacia directamente retorna payload, el atacante captura un token valido → modifica el payload (role → admin) → elimina la firma → pasa la validacion → obtiene privilegios de admin. Arreglo: antes de verify verificar token.split(’.‘).length === 3 y el tercer segmento no este vacio.

Foot-Gun 8: La Lista de Revocacion de JWT No Existe

Sintoma: El usuario cambia contraseña / es deshabilitado por el admin / cierra sesion activamente, el token viejo sigue siendo valido hasta que exp expire. La expiracion del access token de 7 dias significa que el atacante usando el token viejo puede acceder durante 7 dias despues del cambio de contraseña. Sin mecanismo de blacklist / revoke = una vez que el JWT se emite no se puede gestionar.

Por que: JWT esta diseñado para ser stateless — el servidor no almacena tokens, solo verifica la firma. Bueno para escalado horizontal, malo para revocacion. Si quieres “revocar inmediatamente este token”, debes tener blacklist o mecanismo de refresh token.

Arreglo:

  • Access token de expiracion corta + rotacion de refresh token: access token: expiracion de 15 minutos refresh token: expiracion de 7 dias, despues de cada uso regenerar nuevo (rotacion, el refresh token viejo se invalida)
  • refresh token almacenado en BD + blacklist (marcar el refresh token como revocado al cerrar sesion)
  • Revocar todos los refresh tokens al cambiar la contraseña (forzar re-login)
  • Redis blacklist (escenarios de acceso de alta frecuencia usan Redis para cachear tokens revocados, TTL = validez restante del token)

Escenario real: Un usuario SaaS cambio la contraseña pero el atacante uso el token robado accedio durante 7 dias → email del usuario modificado / tarjeta de credito agregada → solo descubierto despues de la queja del servicio al cliente. Arreglo: access token 15 minutos + rotacion de refresh token + cambio de contraseña revoca todos los refresh tokens.

5 Escenarios Reales de Ataque

Escenario 1: Filtracion de Telefono en Texto Plano

Sintoma: Una API SaaS devuelve JWT del usuario conteniendo {user_id: 123, phone: "13812345678", email: "user@example.com"}, el frontend usa este token para mostrar el estado “conectado”. 3 meses despues el JWT secret se filtra, todos los tokens decodificados, 2 millones de telefonos + emails de usuarios obtenidos en un lote.

Arreglo:

  • El payload JWT solo contiene user_id (UUID, no numero derivable)
  • Cuando el frontend necesita mostrar el telefono, usa user_id para llamar a la API del backend para consultar (no confies en la decodificacion del token)
  • Nunca pongas PII en el payload JWT

Escenario 2: Token Falsificado con alg=none

Sintoma: Un servicio Node.js temprano usa jsonwebtoken@4.2.1, el verify no especifica algoritmos, el atacante construye header = {"alg": "none", "typ": "JWT"} + payload {user_id: 1, role: "admin"} + firma dejada vacia, directamente falsifica token admin pasando la validacion.

Arreglo:

  • Forzar whitelist de algoritmos: jwt.verify(token, secret, { algorithms: ['HS256'] })
  • Actualizar jsonwebtoken a la ultima version

Escenario 3: Ataque de Confusion de Clave Publica HS256

Sintoma: El servicio JWT de un banco usa RS256 (clave privada firma, clave publica verifica), clave publica en el gateway de la API, funcion verify jwt.verify(token, publicKey) no especifica algoritmos. El atacante usa la clave publica como secret HMAC para firmar token HS256, el servidor usa la clave publica para “verificar”, pasa → token admin falso transfiere $10 millones.

Arreglo:

  • verify forzar whitelist de algoritmos: jwt.verify(token, publicKey, { algorithms: ['RS256'] })
  • Clave privada / clave publica con nombres estrictamente separados (evitar confusion en getKey)

Escenario 4: exp No Validado, Token Expirado Sigue Siendo Aceptado

Sintoma: Un servicio JWT tiene exp, pero la biblioteca verify por defecto ignoreExpiration: true (por compatibilidad con “tokens permanentes”), todos los tokens expirados pasan. El usuario cambia la contraseña pero el atacante usa el token viejo sigue siendo utilizable durante 30 dias.

Arreglo:

  • Verificar exp explicitamente: jwt.verify(token, secret, { algorithms: ['HS256'], ignoreExpiration: false })
  • Nunca depender de valores por defecto

Escenario 5: Ataque de Eliminacion de Firma

Sintoma: Bug de implementacion de la biblioteca verify de algun JWT: cuando la firma esta vacia directamente retorna payload. El atacante captura un token valido → modifica el payload → elimina la firma → header.payload. envia, evade la verificacion de firma.

Arreglo:

  • Antes de verify verificar token.split(’.‘).length === 3 y el tercer segmento no este vacio
  • Siempre usar biblioteca JWT madura (dividir + verificar tu mismo es facil que tenga bugs)
  • Caso de prueba: token = "header.payload." debe ser rechazado

Plan de Proteccion 7 Dias

Dia 1: Forzar Whitelist de Algoritmo

5 minutos. Revision de codigo verificando todas las llamadas verify JWT, asegurar especificar whitelist de algoritmos:

  • Node.js jsonwebtoken: jwt.verify(token, secret, { algorithms: ['HS256'] })
  • Python PyJWT: jwt.decode(token, secret, algorithms=['HS256'])
  • Java java-jwt: Jwts.parser().verifyWith(key).build().parseSignedClaims(token)
  • Siempre rechazar alg=none

Efecto: Ataque alg=none + ataque de confusion HS256/RS256 completamente bloqueados.

Dia 2: JWT Secret via Variables de Entorno

30 minutos. Mover todos los JWT secret / clave privada de archivos de codigo / config a variables de entorno:

  • Crear .env.example (placeholder, sin secret real, commitear)
  • .gitignore agregar .env
  • Codigo cambiar a `const JWT_SECRET=*** CI usa GitHub Actions secrets + OIDC

Efecto: Riesgo de filtracion de JWT secret en Git reducido a cero.

Dia 3: Siempre Verificar exp + Expiracion Corta

1 hora. Revision de codigo de todas las llamadas verify, asegurar:

  • ignoreExpiration: false especificado explicitamente
  • expiracion del access token ≤ 15 minutos
  • expiracion del refresh token ≤ 7 dias
  • rotacion del refresh token (regenerar despues de cada uso)

Efecto: Despues de la filtracion del token maximo 15 minutos accesible, no 7 dias.

Dia 4: kid Whitelist Estricto

30 minutos. Revision de codigo de la funcion getKey, asegurar:

  • El valor kid debe coincidir con ^[A-Za-z0-9_-]{1,32}$
  • El valor kid debe estar en el conjunto de claves conocido
  • No tratar kid como nombre de archivo / parametro SQL / ruta URL
  • Rechazar campos jwk / jku / x5u propios del token (usar clave configurada en el servidor)

Efecto: Ataque de inyeccion kid completamente bloqueado.

Dia 5: La Firma Debe Verificarse

15 minutos. Revision de codigo de pre-chequeos de verify:

  • token.split(’.‘).length === 3
  • Tercer segmento (firma) no vacio
  • Version de biblioteca es la ultima (sin vulnerabilidades conocidas de eliminacion de firma)
  • Caso de prueba: token = "header.payload." debe ser rechazado

Efecto: Ataque de eliminacion de firma completamente bloqueado.

Dia 6: Mecanismo de Revocacion de refresh token

Medio dia. Implementar rotacion de refresh token + blacklist:

  • Base de datos almacena refresh tokens (asociados user_id + device + estado revoked)
  • Despues de cada uso de refresh token: generar nuevo, marcar viejo como revoked
  • Detectar refresh token revocado siendo usado → revocar todos los tokens de ese usuario (sospechar token robado)
  • Al cambiar la contraseña: revocar todos los refresh tokens, forzar re-login
  • Redis cachea estado revoked (escenarios de acceso de alta frecuencia)

Efecto: Despues de logout / cambio de contraseña / deshabilitacion de cuenta el token viejo es invalido inmediatamente.

Dia 7: Auditoria del Payload JWT

1 hora. Revision de codigo de todas las llamadas sign JWT, asegurar que el payload solo contiene identificadores no sensibles:

  • user_id (UUID, no numero derivable)
  • role (rol, sin exponer estructura organizacional)
  • exp / iat / nbf (timestamps)
  • No incluir: telefono / email / tarjeta de identificacion / tarjeta bancaria / hash de contraseña / direccion

Efecto: Incluso si el token se filtra, la PII no sera expuesta.

Decisiones de Seleccion de Herramienta

Opcion A: Servicios JWT Comerciales (Auth0 / Clerk / Firebase Auth / AWS Cognito)

Mejor para: Equipos medianos-grandes / autenticacion unificada multi-producto / cumplimiento estricto (finanzas / salud).

Ventajas: Seguridad madura / estandar OAuth 2.0 + OIDC / rotacion de refresh token incorporada / blacklist incorporada / auditoria de cumplimiento. Desventajas: Precio alto (Auth0 MAU > 1000 comienza en $240/mes), vendor lock-in, auto-hospedaje dificil.

Opcion B: Auto-implementar con Bibliotecas JWT Maduras (PyJWT / jsonwebtoken / java-jwt)

Mejor para: Individual / equipo pequeño / startup / MVP.

Ventajas: Gratis / flexible / totalmente controlable / compatible con estandar. Desventajas: Auto-implementar revoke / rotacion (facil de buguear), necesita auto-implementar plan de proteccion 7 dias, sin auditoria incorporada.

Opcion C: Decodificador JWT Piick

Mejor para: Cualquier escenario de debug / auditoria / aprendizaje.

100% local sin subida, especialmente adecuado para verificar tokens sospechosos en tiempo de debug / auditar payload JWT / aprender estructura JWT:

  • Decodificar header + payload (base64url decodificacion en un clic, mostrar JSON en texto plano)
  • Parsear exp / iat / nbf / aud / iss / sub (mostrar cuenta regresiva de expiracion, marcar rojo ya expirado)
  • Verificar existencia de firma + algoritmo (advertir alg=none)
  • Verificacion de seguridad de kid / jku / x5u (advertir campos sospechosos)
  • No almacena nada (decodificacion local, destruir al cerrar la pagina)

Arbol de decision:

  • Mediano-grande / multi-producto / cumplimiento → Opcion A (Auth0 / Clerk)
  • Individual / equipo pequeño / MVP → Opcion B (biblioteca madura + plan de proteccion 7 dias)
  • Cualquier debug / auditoria → Opcion C (Piick decodificacion local)

Practicas Recomendadas

  • Siempre forzar whitelist de algoritmo JWT (algorithms: ['HS256'] o ['RS256']), siempre rechazar alg=none
  • Siempre verificar exp (explicito ignoreExpiration: false), access token ≤ 15 minutos
  • Nunca pongas PII en el payload JWT (sin telefono / email / tarjeta de identificacion / tarjeta bancaria)
  • Siempre poner JWT secret en env vars + .gitignore, nunca hardcodear a Git
  • Siempre usar biblioteca JWT madura (PyJWT / jsonwebtoken / java-jwt), no implementar verify tu mismo
  • Siempre usar rotacion de refresh token + blacklist, access token ≤ 15 minutos + refresh token ≤ 7 dias + rotacion
  • Siempre kid whitelist de caracteres (solo permitir [A-Za-z0-9_-]), rechazar campos jwk / jku / x5u propios del token
  • Siempre probar ataque de eliminacion de firma: token = "header.payload." debe ser rechazado
  • Usa Decodificador JWT Piick localmente decodifica tokens sospechosos verifica header / payload / exp / firma, no consume tokens sin subida de log (datos 100% locales), Formateador JSON Piick embellece estructura JSON del payload JWT valida schema, Probador de Regex Piick escribe regex valida formato de claim JWT (iat es numero, exp es numero, sub es UUID), Codificador/Decodificador URL Piick verifica si URL de callback OAuth contiene token en query string, Generador Cron Piick genera programacion de rotacion JWT — conjunto de 5 piezas cubre todos los escenarios dev JWT en linea / debug / seguridad, datos 100% locales sin subida

JWT no es cifrado es codificacion, la firma solo puede evitar manipulacion no puede mantener secreto. La verdadera “seguridad JWT” = forzar whitelist de algoritmo + verificar exp + sin PII + secret via env vars + kid whitelist + firma debe verificar + rotacion de refresh token + blacklist. Guarda en marcadores el Decodificador JWT Piick — verificacion en tiempo de debug de tokens sospechosos en 1 minuto, dev diario ya no se preocupa por filtraciones JWT.