Nimbus deckt JWS, JWE, JWK und JWT mit zwei Schichten ab: Low-Level-Objekte (SignedJWT, ECDSASigner, MACVerifier) und den DefaultJWTProcessor, der Schlüsselauswahl, Signaturprüfung und Prüfung der Claims zusammenführt. Der Ressourcenserver von Spring Security baut darauf auf, deshalb setzen die meisten Spring-APIs genau diese Standardeinstellungen durch.
Mit dem Prozessor ist der JWSVerificationKeySelector die Allowlist: Für ES256 konfiguriert, lehnte er ein RS256-Token und ein HS256-Token mit dem PEM-Text des EC-Schlüssels als Schlüssel mit Another algorithm expected, or no matching key(s) found ab, und ganz ohne Selektor lehnt der Prozessor alles ab. Unsignierte Tokens werden abgelehnt (Unsecured (plain) JWTs are rejected, extend class to handle). Die Low-Level-API hat keinen solchen Schutz – ein aus dem PEM-Text gebauter MACVerifier akzeptierte das gefälschte HS256-Token –, deshalb baut Code, der einen Verifizierer anhand des Headers des Tokens auswählt, den klassischen Algorithm-Confusion-Fehler nach. Verwende den Prozessor, wie es das Beispiel tut.
DefaultJWTClaimsVerifier lässt standardmäßig 60 Sekunden Uhrenabweichung zu, und exp ist optional, sofern der Claim nicht als Pflicht-Claim aufgeführt ist – das Beispiel verlangt sub und exp und legt den Aussteller fest. ES256 lehnt einen P-384-Schlüssel ab (The ES256 algorithm is not allowed or supported by the JWS signer), und eine DER-kodierte Signatur besteht die Prüfung einfach nicht; prüfe die Länge der Signatur mit dem JWT-Debugger.
Version 10.10 bestand den Roundtrip mit den Familien HS, RS, PS und ES sowie mit EdDSA und dem neueren Namen Ed25519. Ed25519 braucht Google Tink im Classpath: Ohne Tink scheiterte das Signieren mit NoClassDefFoundError: com/google/crypto/tink/subtle/Ed25519Sign$KeyPair. ES256K braucht einen Provider mit secp256k1 wie Bouncy Castle, da das JDK keinen mitbringt.
Was ein Identity Provider veröffentlicht, prüfst du mit dem JWKS-Checker; bei verschlüsselten Tokens hilft der JWE-Inspektor.