Decoding jwt token with PyJWT in python giving error Algorithm not supported

31.9k views Asked by At

I am using PyJWT to decode the JWT token coming from keycloak.

eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6MWpiUExrTndMVTBkTHk3a0NIT1pyS2FJd3FPMXFrbThDeGtvVHg2QzFBIn0.eyJleHAiOjE2MjE0MjQwMjEsImlhdCI6MTYyMTQyMzk2MSwiYXV0aF90aW1lIjoxNjIxNDIxNzc0LCJqdGkiOiIwYzY2Y2I0My1lMGY1LTQzNjItYTc2MS1lN2M2OWVhNDM5MjUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbIm1hc3Rlci1yZWFsbSIsImFjY291bnQiXSwic3ViIjoiN2Y2ODBlN2MtZGM4Yy00ZGJiLWJiZDEtMTE0ZGJhYjA2Zjc1IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYW11bmRzZW4tZnJvbnRlbmQiLCJzZXNzaW9uX3N0YXRlIjoiYTM5YzJlNmUtZGNjMS00OTM5LTg0ODItYzk2NGE5ODMxNmYyIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJsb2NhbGhvc3Q6NTAwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiY3JlYXRlLXJlYWxtIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsibWFzdGVyLXJlYWxtIjp7InJvbGVzIjpbInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiYWRtaW5maXJzdCBhZG1pbmxhc3QiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiJhZG1pbmZpcnN0IiwiZmFtaWx5X25hbWUiOiJhZG1pbmxhc3QiLCJlbWFpbCI6ImFkbWludGVzdEBnbWFpbC5jb20ifQ.aksSjBU5hJ1rtn43NtbMt8E6gaGmJXDrtGDI7j0T7eo6PAcnUxG4spYNNhyksXVr3ZFvua2WyTKnZirqaJUI3zzdLj-XkE7zYCYWoJpjXITmmlj5oszD3pcRdGeyUVyQV49tIiUfUFi1KoIt9K016mH2s_beFrN3TYSjuLh5Epdk_dpNBh9YE_1f3opwsEbN2Jgz_j-VB6cQHq17RzWQIVSd6ZvftAWDWdc6nobOvTy1mZAA_DgsXwdjuNc8Qv36ztuDzkT-raCnuLH479ciBOFQZ0946obIE4ddJKpr7lnVupcbQZ6lDM_QZHz1hwkYqgSU-Ui8NHaWlqt4HJ5-9A

my code

import jwt
import traceback


try:
    public_key = """-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhlOIQLHXwZoS3w9SBtvZ1ea4ftWmWnP+HCwlvs7XoJ9EhS+ZQEP7Z25tjW3I8mjUVL0XETrOOjQsD8O2nRBqizJsRaB8L9xsXdJmPHVTx7nphaBPtY5YHxxYqpwEC5rAKtx54YJxw6Ggeicmv+xXtaaDf/VALh5xxpa1U6yP5oqk3yV27yA0beQFVsdugkcfYN0C2FldaUcF9yTUf/KNHTYSu3Ar7iN9U+qEHwaznrLShwh7iknldTKTgEw3liHL8K/5ZlqxHPsL02InwZMaIRic3zNIgVvwedroM6nqZBB4mi1+T0dZn4qsNkG4D0w7IE7MTRgyyYARqrGEq5yOFwIDAQAB
    -----END PUBLIC KEY-----"""

    secret_key = "base-flask-oidc-secret-key"
    token = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6MWpiUExrTndMVTBkTHk3a0NIT1pyS2FJd3FPMXFrbThDeGtvVHg2QzFBIn0.eyJleHAiOjE2MjE0MjQwMjEsImlhdCI6MTYyMTQyMzk2MSwiYXV0aF90aW1lIjoxNjIxNDIxNzc0LCJqdGkiOiIwYzY2Y2I0My1lMGY1LTQzNjItYTc2MS1lN2M2OWVhNDM5MjUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbIm1hc3Rlci1yZWFsbSIsImFjY291bnQiXSwic3ViIjoiN2Y2ODBlN2MtZGM4Yy00ZGJiLWJiZDEtMTE0ZGJhYjA2Zjc1IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYW11bmRzZW4tZnJvbnRlbmQiLCJzZXNzaW9uX3N0YXRlIjoiYTM5YzJlNmUtZGNjMS00OTM5LTg0ODItYzk2NGE5ODMxNmYyIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJsb2NhbGhvc3Q6NTAwMCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiY3JlYXRlLXJlYWxtIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsibWFzdGVyLXJlYWxtIjp7InJvbGVzIjpbInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiYWRtaW5maXJzdCBhZG1pbmxhc3QiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiJhZG1pbmZpcnN0IiwiZmFtaWx5X25hbWUiOiJhZG1pbmxhc3QiLCJlbWFpbCI6ImFkbWludGVzdEBnbWFpbC5jb20ifQ.aksSjBU5hJ1rtn43NtbMt8E6gaGmJXDrtGDI7j0T7eo6PAcnUxG4spYNNhyksXVr3ZFvua2WyTKnZirqaJUI3zzdLj-XkE7zYCYWoJpjXITmmlj5oszD3pcRdGeyUVyQV49tIiUfUFi1KoIt9K016mH2s_beFrN3TYSjuLh5Epdk_dpNBh9YE_1f3opwsEbN2Jgz_j-VB6cQHq17RzWQIVSd6ZvftAWDWdc6nobOvTy1mZAA_DgsXwdjuNc8Qv36ztuDzkT-raCnuLH479ciBOFQZ0946obIE4ddJKpr7lnVupcbQZ6lDM_QZHz1hwkYqgSU-Ui8NHaWlqt4HJ5-9A"
    # token_json = jwt.decode(token, secret_key, algorithms=['HS256', 'RS256'], audience='account')
    token_json = jwt.decode(token, public_key, algorithms=['HS256', 'RS256'], audience='account')
    print(access_token_json)
    
except Exception:
    print(traceback.print_exc())

according to jwt.io, it is showing header

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "z1jbPLkNwLU0dLy7kCHOZrKaIwqO1qkm8CxkoTx6C1A"
}

i tried with public key as well as secret key, both are giving me error

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 232, in _verify_signature
    alg_obj = self._algorithms[alg]
KeyError: 'RS256'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "jwt_test.py", line 16, in <module>
    access_token_json = jwt.decode(access_token, public_key, algorithms=['HS256', 'RS256'], audience='account')
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jwt.py", line 119, in decode
    decoded = self.decode_complete(jwt, key, algorithms, options, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jwt.py", line 95, in decode_complete
    **kwargs,
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 149, in decode_complete
    self._verify_signature(signing_input, header, signature, key, algorithms)
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 239, in _verify_signature
    raise InvalidAlgorithmError("Algorithm not supported")
jwt.exceptions.InvalidAlgorithmError: Algorithm not supported

if i am removing 'RS256' from algorithms list.

token_json = jwt.decode(token, public_key, algorithms=['HS256'], audience='account')

then i am getting error.

Traceback (most recent call last):
  File "jwt_test.py", line 18, in <module>
    token_json = jwt.decode(token, public_key, algorithms=['HS256'], audience='account')
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jwt.py", line 119, in decode
    decoded = self.decode_complete(jwt, key, algorithms, options, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jwt.py", line 95, in decode_complete
    **kwargs,
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 149, in decode_complete
    self._verify_signature(signing_input, header, signature, key, algorithms)
  File "/usr/local/lib/python3.7/site-packages/jwt/api_jws.py", line 229, in _verify_signature
    raise InvalidAlgorithmError("The specified alg value is not allowed")

How do i solve this issue.

Thanks in advance!

################### answer #######################

I was able to solve it by

Installing cryptography as suggested by @KlausD in the comment

pip install cryptography

and also changed public key to

public_key = """-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhlOIQLHXwZoS3w9SBtvZ1ea4ftWmWnP+HCwlvs7XoJ9EhS+ZQEP7Z25tjW3I8mjUVL0XETrOOjQsD8O2nRBqizJsRaB8L9xsXdJmPHVTx7nphaBPtY5YHxxYqpwEC5rAKtx54YJxw6Ggeicmv+xXtaaDf/VALh5xxpa1U6yP5oqk3yV27yA0beQFVsdugkcfYN0C2FldaUcF9yTUf/KNHTYSu3Ar7iN9U+qEHwaznrLShwh7iknldTKTgEw3liHL8K/5ZlqxHPsL02InwZMaIRic3zNIgVvwedroM6nqZBB4mi1+T0dZn4qsNkG4D0w7IE7MTRgyyYARqrGEq5yOFwIDAQAB\n-----END PUBLIC KEY-----"""
3

There are 3 answers

1
uinstinct On

After reading the PyJWT installation guide again, it seems that for certain signature algorithms like RSA, the python cryptography library needs to be installed.

I resolved the problem by installing the dependecy:

pip install pyjwt[crypto]
0
hygull On

I also faced the same issue (Python version 3.6.7 on Mac) but the solution was totally different that I resolved with the help of provided answers in addition to some other steps as well.

Note: Don't think, if you have activated virtual environment and keeping it active for a long time, it will work with same efficiency as per our expectations. So make sure to reactivate it even you keep your PC, Laptop, System etc. in sleep mode.

See below what actually I faced and finally got it resolved.

How I had generated the Private & Public keys?

Below are the 2 commands to execute to get private & public keys.

> openssl genrsa -out jwt-key 4096
> openssl rsa -in jwt-key -pubout > jwt-key.pub

Get JWT (Encode)

encoded_jwt = jwt.encode({ "user_id": 1 }, private_key, algorithm='RS256')

It was successful in the project with different virtual environment. Now I tried to decode this JWT in another project with different virtual environment (which had been activated few days back and was still active).

payload = jwt.decode(encoded_jwt, public_key, algorithms=['RS256'])

And saw this error/exception message.

3.6/site-packages/jwt/api_jws.py", line 226, in _verify_signature
raise InvalidAlgorithmError('Algorithm not supported')
jwt.exceptions.InvalidAlgorithmError: Algorithm not supported

Oops! Let's try to solve it!

How did I resolve?

After reading the answers I followed the steps and installed pyjwt[crypto] , cryptography (anyone of this) packages inside my already activated virtual environment but then also my problems did not get resolve. It was making me think about trying another algorithm but I thought to try and brainstorm for other solutions.

I just took a look inside <virtualenv_dir>/lib/site-packages/ and found there was no cryptography package installed rather it was installed outside in the actual Python environment.

So now, I had some idea to resolve and performed the below steps to resolve the issue.

  1. Deactivated the virtual environment
  2. Ran pip uninstall pyjwt[crypto]
  3. Ran pip uninstall cryptography
  4. Activated the virtual environment
  5. Ran pip install pyjwt[crypto]
  6. Ran pip install cryptography

Now, when I decoded the encoded JWT, it worked well.

Decode JWT

> payload = jwt.decode(encoded_jwt, public_key, algorithms=['RS256'])`
> payload
{ "user_id": 1 }

Finally, the bug is resolved.

0
Nahid Akhtar On

Why the error occurs is explained Here. You can solve the issue just avoid checking the audience data of the jwt:

import jwt
ALGORITHM = "HS256"

options={
        'verify_exp': False,  # Skipping expiration date check
        'verify_aud': False 
        }

    try:
        payload = jwt.decode(token, YOUR_SECRET_KEY, algorithms=[ALGORITHM], options=options)
    except Exception as e:
        raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))