-
-
Notifications
You must be signed in to change notification settings - Fork 716
Description
Hello,
I spend a few hours today for a bug that shouldn't have been there. I set up my python application where I recieve a jwt token from oauth-proxy, validate, decode and echo the contents.
Running locally, everything went perfect. Running in a container I got the message "The JWK Set did not contain any usable keys". I checked, oauth configs, credentials, my code, put a few hours into trying to debug the python code while running in podman.
Then after a few hours my colleague helped and ran the project on his machine. He got the same error.
So what does his machine has not, that mine has? Dependencies.
After another hour of debuging, we found out, that my jwt token is encoded with RSA. For pyjwt to decode the key we need to use RSA. To use RSA the cryptography is nessecary. I got this installed in my global dependencies and forgot to use an env.
The thing is:
Alls this could have been prevented, if the raised error message would be "found RSA - cannot decode because dependency cryptography is missing"
Instead the error handling is as follows:
api_jwk.py - PyJWKSet:
class PyJWKSet:
def __init__(self, keys: list[dict]) -> None:
self.keys = []
if not keys:
raise PyJWKSetError("The JWK Set did not contain any keys")
if not isinstance(keys, list):
raise PyJWKSetError("Invalid JWK Set value")
for key in keys:
try:
*self.keys.append(PyJWK(key))*
*except PyJWKError:*
# skip unusable keys
*continue*
if len(self.keys) == 0:
raise PyJWKSetError("The JWK Set did not contain any usable keys")
->
class PyJWK:
def __init__(self, jwk_data, algorithm=None):
self._algorithms = get_default_algorithms()
->
ef get_default_algorithms():
"""
Returns the algorithms that are implemented by the library.
"""
default_algorithms = {
"none": NoneAlgorithm(),
"HS256": HMACAlgorithm(HMACAlgorithm.SHA256),
"HS384": HMACAlgorithm(HMACAlgorithm.SHA384),
"HS512": HMACAlgorithm(HMACAlgorithm.SHA512),
}
if has_crypto:
default_algorithms.update({
"RS256": RSAAlgorithm(RSAAlgorithm.SHA256),
...
and has_crypto comes from algorithms.py
try:
import cryptography.exceptions
....
except ModuleNotFoundError:
has_crypto = False
As summary:
You iterate through every key, looking if there is an algorithm, find that a dependecie is missing and skip this key, and buring the error message. Afterwards the length of the list of keys is 0 - you get the message of no usable keys and are none the wiser, why this is the case.
please rework you try catch error flow, so that a developer knows when a dependency is missing for the current key!