lcobucci/jwt trennt Parsen, Signieren und Validierung: Eine Configuration enthält den Signierer und die Schlüssel, parser()->parse() liest ein Token, ohne irgendetwas zu prüfen, und validator()->assert() wendet die Constraints an, die du übergibst. Ein Aufruf von assert() ohne Constraints wirft NoConstraintsGiven – so schreibst du kaum versehentlich eine Validierung, die nichts prüft.
SignedWith legt Signierer und Schlüssel fest: Ein RS256-Token und ein mit dem PEM-Text des EC-Schlüssels gefälschtes HS256-Token scheiterten beide mit Token signer mismatch. Unsignierte Tokens lassen sich nicht einmal parsen (The JWT string is missing the Signature part). Schlüssellängen werden schon beim Signieren durchgesetzt – ES256 lehnte einen P-384-Schlüssel ab (The length of the provided key is different than 256 bits), HS256 einen 40-Bit-Schlüssel –, sodass fehlerhafte Tokens gar nicht erst entstehen.
Auch die Zeitprüfungen sind Constraints und laufen daher nur, wenn sie aufgeführt sind: Ein Token, das eine Stunde zuvor abgelaufen war, bestand SignedWith allein. LooseValidAt prüft exp, nbf und iat, sofern vorhanden, und akzeptierte ein Token ohne exp; StrictValidAt verlangt alle drei – ein Token ohne iat scheiterte mit "Issued At" claim missing, eines mit iat und exp, aber ohne nbf mit "Not Before" claim missing. Beide nehmen ein optionales Toleranzintervall (Leeway) entgegen, standardmäßig null. Das Beispiel setzt alle drei Claims und prüft Signatur, Aussteller und strikte Gültigkeit in einem Aufruf.
Version 5.6.1 unterstützt HS, RS und ES bei 256/384/512 sowie EdDSA; es gibt keine Signierer für PS* und kein ES256K, sodass Tokens von Ausstellern, die RSA-PSS verwenden, web-token brauchen. ES256-Signaturen bestehen aus 64 Byte rohem r‖s, und eine DER-Signatur scheitert mit Token signature mismatch; der JWT-Debugger zeigt, welche Kodierung ein Token enthält.