27

I am using pyjwt library for decoding the JWT token. I got this error when I am decoding. The code was given in the documantation.

import jwt

encoded_jwt='''eyJ0eXAiOiJKV1QiLCJhbG......'''
secret=b''''-----BEGIN PUBLIC KEY-----
MIIFRjCCBC6gAwIBAgIQCIdSGhpikQCjOIY154XoqzANBgkqhkiG9w0BAQsFADBN
......
-----END PUBLIC KEY-----'''

print(jwt.decode(encoded_jwt, secret , algorithms=['RS256']))

raise ValueError("Could not deserialize key data.") ValueError: Could not deserialize key data.

Could You please help me in resolving it beacuse when I use this it in the JWT website it's working.

This is the full error log..

Traceback (most recent call last): File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/jwt/algorithms.py", line 205, in prepare_key key = load_pem_private_key(key, password=None, backend=default_backend()) File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/cryptography/hazmat/primitives/serialization.py", line 20, in load_pem_private_key return backend.load_pem_private_key(data, password) File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1014, in load_pem_private_key password, File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1233, in _load_key self._handle_key_loading_error() File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1291, in _handle_key_loading_error raise ValueError("Could not deserialize key data.") ValueError: Could not deserialize key data.

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/home/sathiyakugan/PycharmProjects/JWTsample/sample.py", line 45, in print(jwt.decode(encoded_jwt, secret , algorithms=['RS256'])) File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/jwt/api_jwt.py", line 93, in decode jwt, key=key, algorithms=algorithms, options=options, **kwargs File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/jwt/api_jws.py", line 157, in decode key, algorithms) File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/jwt/api_jws.py", line 221, in _verify_signature key = alg_obj.prepare_key(key) File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/jwt/algorithms.py", line 207, in prepare_key key = load_pem_public_key(key, backend=default_backend()) File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/cryptography/hazmat/primitives/serialization.py", line 24, in load_pem_public_key return backend.load_pem_public_key(data) File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1040, in load_pem_public_key self._handle_key_loading_error() File "/home/sathiyakugan/PycharmProjects/Python/venv/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1291, in _handle_key_loading_error raise ValueError("Could not deserialize key data.") ValueError: Could not deserialize key data.

Process finished with exit code 1

10 Answers10

16

Its a good idea to use your RSA keys with OpenSSL:

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

Reference: link

Javad Asoodeh
  • 299
  • 3
  • 12
  • I had a similar issue and this was the solution for my problem. Thanks, and recommend answer (although I did not check the others) – xCovelus Nov 03 '20 at 11:59
14

Use the authlib library, I never managed to decode keycloak tokens with pyjwt. You need a public_key, I assume you have it.

from authlib.jose import jwt
key = '-----BEGIN PUBLIC KEY-----\n' + public_key + '\n-----END PUBLIC KEY-----'
key_binary = key.encode('ascii')

try:
    claims = jwt.decode(encoded,key_binary)
    claims.validate()
    #do some logic here
    #...

ProTip: you may grab the public key easily from your auth server (in my case Keycloak) at some endpoint:

url = 'http://localhost:8080/auth/realms/your_realm'
with  urllib.request.urlopen(url) as r:
    response = r.read()
    public_key = json.loads(response)['public_key']
psnx
  • 618
  • 7
  • 8
  • 1
    "I never managed to decode keycloak tokens with pyjwt" I'm late to the party here, but had a similar issue using pyjwt to validate JWTs from Keycloak. I finally realized it's because pyjwt is expecting the PUBLIC-KEY value only (not a full PEM certificate). I got it to work by converting the x509 cert which Keycloak provides into a PEM file (by wrapping it in "-----BEGIN/END CERTIFICATE-----" lines), and using the following openssl command to extract the PUBLIC-KEY value: `openssl x509 -pubkey -noout -in certificate.pem`. The resulting public key output then works with pyjwt. – loneboat Jul 03 '20 at 04:36
  • 1
    FWIW: https://renzolucioni.com/verifying-jwts-with-jwks-and-pyjwt/ – Bill Horvath Nov 29 '21 at 04:20
14

If you get this error double check your public key is exactly right, new lines are important.

key = '''-----BEGIN PUBLIC KEY-----
<main key here>
-----END PUBLIC KEY-----'''
Matthew Wilcoxson
  • 3,432
  • 1
  • 43
  • 48
11

How did you encode your jwt? Use one of the approaches below

Encoding & Decoding Tokens with RS256 (RSA)

encoded = jwt.encode({'some': 'payload'}, private_key, algorithm='RS256')
decoded = jwt.decode(encoded, public_key, algorithms='RS256')

Reading the Claimset without Validation

jwt.decode(encoded, verify=False)
{u'some': u'payload'}

Or use same secret to encode and decode the jwt, one of the approach should work. In my case I used jwt.decode(token, verify=False) because my server has already did the signature validation for me, I only need to get the claimset.

  • 6
    This is not working for me, It says `ValueError: Could not deserialize key data.` on encoding data. – Chitrank Dixit Dec 05 '19 at 20:23
  • Which one is not working for you the decode method with a public key or without the public key – Venkatesh Marepalli Dec 05 '19 at 22:24
  • In my case the issue was with encoding, we can encode with the above flow but we need to load private key properly, I found this on : https://github.com/jpadilla/pyjwt/issues/320, after this I was able to do encode and decode. – Chitrank Dixit Dec 06 '19 at 04:30
10

There are some issues in the pyjwt library. and you must get the public key from the certificate.

I used openssl x509 -pubkey -noout -in cert.pem > pubkey.pem

then from the public key I could easily decode it using authlib library.

from authlib.specs.rfc7519 import jwt

encoded_jwt='''eyJ0eXAiOiJ....'''
secret=b'''-----BEGIN PUBLIC KEY-----
......
-----END PUBLIC KEY-----'''
claims = jwt.decode(encoded_jwt, secret)
print(claims)
2

MacOS Catalina 10.15.4 Python 2.7.16.

This solved the problem in my case

pip install cryptography==2.3
Kamil.S
  • 5,205
  • 2
  • 22
  • 51
1

If the problem was the fact that you are using certificate you can just extract public / private key from the certificate:

from cryptography.x509 import load_pem_x509_certificate

cert_str = b"-----BEGIN CERTIFICATE-----MIIDETCCAfm..."
cert_obj = load_pem_x509_certificate(cert_str)
public_key = cert_obj.public_key()
private_key = cert_obj.private_key()

Source: https://pyjwt.readthedocs.io/en/stable/faq.html

Piotr Siejda
  • 197
  • 8
0

For me, there were spaces in the key (silly IDE) which caused this issue, make sure that's not the case with you

Gautam Jain
  • 651
  • 8
  • 16
0

save the public key into the file and pass the path and use that.

  1. public_key = open(path).read()
  2. payload = jwt.decode(token, public_key, algorithms=['RS256'])
0

For me what worked was setting the jwt verify signature to false:

import jwt 

token = st_javascript('''localStorage.getItem("some_token")''') # fetch your token of interest
decoded = jwt.decode(token, options={"verify_signature": False}) # decode the token

Note: This bypasses JWT verification and should only be used if you don't care wether the JWT is cryptographically invalid or valid.

For more info you can view the jwt documentation.

Max Campbell
  • 595
  • 9
  • 22