IMO this is a defect (sabotage? plain incompetence?) in the specs, full stop.
RFC 7519 (the JWT spec) delegates all signature / authentication validation to the JWS and JWE specs. (And says that an unholy mechanism shall be used to determine whether to follow the JWS validation algorithm or the JWE algorithm.)
JWS even discusses algorithm verification (https://www.rfc-editor.org/rfc/rfc7515.html#section-10.6), but does not suggest, let alone require, the absolutely mindbendingly obvious way to do it: when you have a key used for verificaiton, the algorithm specification is part of the key. If I tell a library to verify that a given untrusted input is signed/authenticated by a key, the JWS design is:
bool is_it_valid(string message, string key); // where key is an HMAC secret or whatever
where VerificationKey is an algorithm and the key. If you say to verify with an HMAC-SHA256 key and the actual message was signed with none or with HMAC-SHA384 or anything else, it is invalid. If you have a database and you know your key bits but not what cryptosystem those bits belong to, your database is wrong.
The JWE spec is not obviously better. I wouldn't be utterly shocked if it could be attacked by sending a message to someone who intends to use, say, a specific Ed25519 public key, but setting the algorithm to RSA and treating the Ed25519 public key as a comically short RSA key.
RFC 7519 (the JWT spec) delegates all signature / authentication validation to the JWS and JWE specs. (And says that an unholy mechanism shall be used to determine whether to follow the JWS validation algorithm or the JWE algorithm.)
JWS even discusses algorithm verification (https://www.rfc-editor.org/rfc/rfc7515.html#section-10.6), but does not suggest, let alone require, the absolutely mindbendingly obvious way to do it: when you have a key used for verificaiton, the algorithm specification is part of the key. If I tell a library to verify that a given untrusted input is signed/authenticated by a key, the JWS design is:
and this is wrong. You do it like this: where VerificationKey is an algorithm and the key. If you say to verify with an HMAC-SHA256 key and the actual message was signed with none or with HMAC-SHA384 or anything else, it is invalid. If you have a database and you know your key bits but not what cryptosystem those bits belong to, your database is wrong.The JWE spec is not obviously better. I wouldn't be utterly shocked if it could be attacked by sending a message to someone who intends to use, say, a specific Ed25519 public key, but setting the algorithm to RSA and treating the Ed25519 public key as a comically short RSA key.