lcobucci/jwt separa el análisis, la firma y la validación: una Configuration contiene el firmante y las claves, parser()->parse() lee un token sin comprobar nada y validator()->assert() aplica las restricciones que le pasas. Llamar a assert() sin restricciones lanza NoConstraintsGiven, lo que hace difícil escribir por accidente una validación que no compruebe nada.
SignedWith fija el firmante y la clave: un token RS256 y un token HS256 falsificado con el texto PEM de la clave EC fallaron ambos con Token signer mismatch. Los tokens sin firmar ni siquiera se pueden analizar (The JWT string is missing the Signature part). Los tamaños de clave se validan al firmar —ES256 rechazó una clave P-384 (The length of the provided key is different than 256 bits) y HS256 rechazó una clave de 40 bits—, lo que impide que lleguen a producirse tokens mal formados.
Las comprobaciones de tiempo también son restricciones, así que solo se ejecutan si se incluyen: un token que había caducado una hora antes superó SignedWith por sí solo. LooseValidAt comprueba exp, nbf e iat cuando están presentes y aceptó un token sin exp; StrictValidAt exige los tres: un token sin iat falló con "Issued At" claim missing, y uno con iat y exp pero sin nbf, con "Not Before" claim missing. Ambas admiten un intervalo de tolerancia opcional, cero por defecto. El ejemplo fija los tres claims y comprueba la firma, el emisor y la validez estricta en una sola llamada.
La 5.6.1 admite HS, RS y ES de 256/384/512 y EdDSA; no hay firmantes PS* ni ES256K, así que los tokens de emisores que usan RSA-PSS necesitan web-token. Las firmas ES256 son 64 bytes de r‖s en bruto, y una firma DER falla con Token signature mismatch; el decodificador de JWT muestra qué codificación lleva un token.