3 ms·
I don't think it's called out in the RFC because when you have a list of all the keys that are accepted, it makes it so the algorithm is effectively whitelisted
by benatkin 5y ago
I don't think it's called out in the RFC because when you have a list of all the keys that are accepted, it makes it so the algorithm is effectively whitelisted.
- CiPHPerCoder 5y agoIf I give you a map of kid -> key material that looks like this: { "my-super-cool-key-id": "some hs256 secret key string goes here", "another-key-id": "-----BEGIN RSA PUBLIC KEY-----\n ... snip ...", "yet-another-key-id": "----BEGIN EC PUBLIC KEY-----\n... snip ..." } And let's say you've got three different API endpoints, which each hard-code a specific algorithm (one HS256, one PS256, one ES256). But, because of the framework you're developing in, you're expected to provide a single configuration object containing a map of key IDs used by the entire application. (This is a common framework quirk.) What stops you from swapping out the kid in a JWT's header and getting the underlying library to use the wrong key type for the endpoint that accepts HS256? { "alg": "HS256", - "kid": "my-super-cool-key-id", + "kid": "yet-another-key-id", "typ": "JWT" } The answer varies per implementation. The JWT standards do not call this misuse potential out at all. Strictly listing the keys does not, at all, hard-code the algorithm those keys are used with in every possible programming language and runtime. Some languages (Java) accidentally prevent this through type safety in the low-level crypto APIs. Others accidentally prevent this by not supporting the kid header. I have yet to see a JWT library that deliberately prevents this misuse potential. Is that the library's fault? Or their defaults' fault? EDIT: The fix, by the way, requires doing this: { "my-super-cool-key-id": { "alg": "HS256", "key": "some hs256 secret key string goes here" }, "another-key-id": { "alg": "PS256", "key": "-----BEGIN RSA PUBLIC KEY-----\n ... snip ..." }, "yet-another-key-id": { "alg": "ES256", "key": "----BEGIN EC PUBLIC KEY-----\n... snip ..." } } And then verifying that the alg for the key matches the alg for the token before attempting to verify the signature/MAC.