El error 'Invalid signature' en JWT y otros errores comunes, explicados
Qué provoca realmente un error de firma inválida en un JWT, por qué es distinto de un token expirado, y cómo leer el header y el payload de un token para encontrar el problema real en segundos.
Un JWT son tres partes codificadas en Base64URL unidas por puntos — header.payload.signature. El header y el payload son solo JSON codificado y cualquiera puede leerlos sin ningún secreto; la firma es la única parte que realmente demuestra que el token fue emitido por quien tiene la clave secreta, y de ahí viene casi cualquier error confuso de JWT.
'Invalid signature' casi nunca significa que el token esté mal formado
Este error significa que el servidor recalculó la firma con su propia clave secreta y obtuvo un resultado distinto al que traía el token. La estructura y el JSON del token suelen ser perfectamente válidos — el desajuste casi siempre lo provoca una de estas tres cosas: la clave secreta usada para verificar no coincide con la usada para firmar (habitual justo después de rotar una clave o entre entornos), el algoritmo del header (alg) no coincide con lo que espera el servidor, o el payload fue manipulado o re-codificado después de firmar, incluso por algo tan pequeño como reserializar el JSON con distinto orden de claves o espacios.
'Token expired' es un problema completamente distinto, y mucho más simple
Este no tiene nada que ver con la firma — significa que la firma se verificó correctamente, pero el claim 'exp' del payload es una fecha en el pasado. Es el token funcionando exactamente como está diseñado. La solución es simplemente obtener un token nuevo (normalmente mediante un flujo de refresh token), no tocar la lógica de firma.
'alg: none' y por qué siempre debería rechazarse
La especificación de JWT técnicamente permite un valor de 'alg' igual a 'none', es decir, un token sin ninguna firma. Un servidor que confía en el algoritmo indicado dentro del propio token — en lugar de aceptar solo el o los algoritmos que espera explícitamente — puede ser engañado para aceptar un token totalmente sin firmar, fabricado por un atacante. Valida siempre contra una lista explícita de algoritmos permitidos en el servidor, nunca confíes en el campo 'alg' del token.
Cómo depurarlo de verdad en menos de un minuto
Pega el token en un decodificador y comprueba tres cosas en orden: si el 'alg' del header coincide con lo que firma tu servidor, si el claim 'exp' está en el futuro, y si el payload contiene los claims (como 'sub' o un rol personalizado) que tu código espera leer. Nueve de cada diez veces, el fallo está en uno de esos tres campos, no en la criptografía en sí.
Nuestro decodificador de JWT separa el header, el payload y la firma al instante y marca automáticamente un token expirado — como todo funciona en tu navegador, es seguro pegar un token real y en uso mientras depuras un problema en producción.