Nimbus は JWS、JWE、JWK、JWT を 2 つのレイヤーで扱います。低レベルのオブジェクト(SignedJWT、ECDSASigner、MACVerifier)と、鍵の選択、署名のチェック、クレームのチェックをまとめる DefaultJWTProcessor です。Spring Security のリソースサーバーはこの上に構築されているため、そのデフォルトがほとんどの Spring の API で適用されるルールになります。
プロセッサーを使う場合は、JWSVerificationKeySelector が許可リストになります。ES256 用に設定したセレクターは、RS256 トークンと、EC 鍵の PEM テキストを鍵とした HS256 トークンを Another algorithm expected, or no matching key(s) found で拒否しました。セレクターがまったくない場合は、すべてを拒否します。署名のないトークンは拒否されます(Unsecured (plain) JWTs are rejected, extend class to handle)。低レベルの API にはこうした保護がありません。PEM テキストから作成した MACVerifier は、その偽造された HS256 トークンの検証を通しました。そのため、トークンのヘッダーに従って検証器を選ぶコードは、古典的なアルゴリズム混同のバグを再現してしまいます。サンプルのように、プロセッサーを使ってください。
DefaultJWTClaimsVerifier はデフォルトで 60 秒の時刻のずれを許容し、exp は必須クレームとして指定しない限り任意です。サンプルでは sub と exp を必須にし、発行者を固定しています。ES256 は P-384 の鍵を拒否し(The ES256 algorithm is not allowed or supported by the JWS signer)、DER エンコードの署名は単に検証に失敗します。署名の長さは JWT デバッガーで確認してください。
バージョン 10.10 では、HS、RS、PS、ES の各ファミリーに加え、EdDSA と新しい名前の Ed25519 でも、署名と検証を往復で確認できました。Ed25519 にはクラスパス上の Google Tink が必要で、ない場合は署名が NoClassDefFoundError: com/google/crypto/tink/subtle/Ed25519Sign$KeyPair で失敗しました。JDK には secp256k1 がないため、ES256K には Bouncy Castle のような secp256k1 を備えたプロバイダーが必要です。
ID プロバイダーが公開している内容は JWKS チェッカーで、暗号化されたトークンは JWE インスペクターで確認してください。