TypeError: load_pem_private_key() missing 1 required positional argument: 'backend'
Asked Answered
S

6

10

I'm trying to pull adobe analytics data using adobe API2.0, I'm a newbie in this, So following this repo I did provide all details, such as APIKEY, techaccountID, org_id, client secret, modified config.ini. while generating the JWT token, I was getting the below error.

TypeError: load_pem_private_key() missing 1 required positional argument: 'backend'

Here is my code,

def get_jwt_token(config):
    with open(config["key_path"], 'r') as file:
        private_key = file.read()

    return jwt.encode({
        "exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=30),
        "iss": config["orgid"],
        "sub": config["technicalaccountid"],
        "https://{}/s/{}".format(config["imshost"], config["metascopes"]): True,
        "aud": "https://{}/c/{}".format(config["imshost"], config["apikey"])
    }, private_key, algorithm='RS256')


config = dict(config_parser["default"])
jwt_token = get_jwt_token(config)
logger.info("JWT Token: {}".format(jwt_token))
access_token = get_access_token(config, jwt_token)
logger.info("Access Token: {}".format(access_token))

Here is the error message,

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-17-8c61bcf6ee58> in <module>
      1 config = dict(config_parser["default"])
----> 2 jwt_token = get_jwt_token(config)
      3 logger.info("JWT Token: {}".format(jwt_token))
      4 access_token = get_access_token(config, jwt_token)
      5 logger.info("Access Token: {}".format(access_token))

<ipython-input-3-d22e1d6f4ebb> in get_jwt_token(config)
      9         "https://{}/s/{}".format(config["imshost"], config["metascopes"]): True,
     10         "aud": "https://{}/c/{}".format(config["imshost"], config["apikey"])
---> 11     }, private_key, algorithm='RS256')

~\AppData\Local\Continuum\anaconda3\lib\site-packages\jwt\api_jwt.py in encode(self, payload, key, algorithm, headers, json_encoder)
     61         ).encode("utf-8")
     62 
---> 63         return api_jws.encode(json_payload, key, algorithm, headers, json_encoder)
     64 
     65     def decode_complete(

~\AppData\Local\Continuum\anaconda3\lib\site-packages\jwt\api_jws.py in encode(self, payload, key, algorithm, headers, json_encoder)
    108         try:
    109             alg_obj = self._algorithms[algorithm]
--> 110             key = alg_obj.prepare_key(key)
    111             signature = alg_obj.sign(signing_input, key)
    112 

~\AppData\Local\Continuum\anaconda3\lib\site-packages\jwt\algorithms.py in prepare_key(self, key)
    248                         key = load_ssh_public_key(key)
    249                     else:
--> 250                         key = load_pem_private_key(key, password=None)
    251                 except ValueError:
    252                     key = load_pem_public_key(key)

TypeError: load_pem_private_key() missing 1 required positional argument: 'backend'

I tried with a different approach as specified in this video but said approach also resulted in the same error https://www.youtube.com/watch?v=eSh2r3ZTCQU

I did Google, but couldn't get the solution. From the error, I can interpret I should provide an argument backend but where should I provide it? Can someone please help me what is wrong here?

Salish answered 1/2, 2021 at 4:47 Comment(0)
D
11

I got same error with jwt.decode but only in CI (linux) and it worked with my mac.

Check with python -m jwt.help what is your cryptography version. pyjwt 2 requires cryptography >= 3 and for some reason for me it is 2.9.2 in CI so that would explain why it fails for me.

There is commit that updates pyjwt[crypto] to require valid cryptography package but for some reason it is not shown in changelogs and also I fixed issue by manually adding cryptography>=3.3.1,<4.0.0 to requirements.txt

Decided answered 3/2, 2021 at 9:53 Comment(1)
#66208504 Can you please check if you can answer this question? Thanks a lot for helpSalish
P
3

The cryptography module made the backend arguments optional starting with version 3.1.

For older versions, call load_pem_private_key (or load_ssh_public_key, or load_..._..._key) explicitly with backend=default_backend(), like this:

from cryptography.hazmat.primitives.serialization import load_pem_public_key
from cryptography.hazmat.backends import default_backend

pem_key = load_pem_private_key(key_data, backend=default_backend())
jwt.encode({...}, key = pem_key, algorithm = 'RS512')

See https://cryptography.io/en/3.3.1/hazmat/backends/index.html#getting-a-backend

Psychosomatic answered 30/11, 2021 at 16:45 Comment(0)
U
1

Try to install with

$ python3 -m pip install --upgrade pyjwt[crypto]
...
Note: you may need to restart the kernel to use updated packages.

Then restart the IDE/terminal.

Urbanite answered 4/11, 2021 at 21:35 Comment(0)
T
0

I have had the same error but with my Raspberry Pi project. I tired the python example for the Google Cloud IoT Core. I share my experience if someone faces the same problem.

I have tried different version combinations of pyjwt and cryptography, but the problem persisted.

The issue is that pyjwt does not set a default backend if none is given. I have tired the example on my Mac with Python 3.9 and it worked.

But Python 3.9 does not work on the Raspberry Pi because there are some missing dependencies. So i compiled Python 3.8.12 on my Raspberry Pi and the error is gone.

Here is a guide for compiling Python.

https://raspberrytips.com/install-latest-python-raspberry-pi/

Install these Libraries first or pip will not work because the ssl modul is missing.

sudo apt install libssl-dev
sudo apt install libncurses5-dev
sudo apt install libsqlite3-dev
sudo apt install libreadline-dev
sudo apt install libtk8.6
sudo apt install libgdm-dev
sudo apt install libdb4o-cil-dev
sudo apt install libpcap-dev

I do not know if all are necessary, but it worked.

pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available

Tuesday answered 8/10, 2021 at 12:9 Comment(0)
F
0

The above error used to appear in case of when we try to establish a connection with mongodb atlas using jupyter notebook through python, importing pymongo package and copying connection string from atlas,but when we execute we used to get this error.

To resolve this error, just follow these steps: 1)import ssl ssl_cert_reqs=ssl.CERT_NONE 2) in the connection string,put comma and paste tls=True,tlsAllowInvalidCertificates=True

2nd steps looks like : import pymongo client = pymongo.MongoClient("mongodb+srv://username:[email protected]/myFirstDatabase?retryWrites=true&w=majority",tls=True,tlsAllowInvalidCertificates=True) db = client.test

print(db)

you'll see the above error got resolved.

Fowle answered 14/2, 2022 at 10:42 Comment(0)
C
0

My problem is related to the jwt.decode() function also.

jwt_payload = jwt.decode(jwt_message.encode("utf-8"), keystring.encode("utf-8"), algorithms=["RS256"])

Since 2024-05-28 16:59 the call to this function (sometimes) generated an exception: The token is not yet valid (iat)

But after examining the header I saw that the iat date was valid.

Then after a few days almost every call to jwt.decode() function generated the exception. And since today (2024-06-04) there was no error generated at all: the program just freezed! I had done no changes to the Python libraries (cryptography==37.0.4, PyJWT==2.8.0, certifi==2023.7.22)

Since I was decoding instead of encoding and not using my private key I decided to experiment with the arguments to the jwt.decode() function and after adding the options={"verify_signature": False} argument the program no longer freezed:

jwt_payload = jwt.decode(jwt_message.encode("utf-8"), keystring.encode("utf-8"), algorithms=["RS256"], options={"verify_signature": False})

But this is not the correct way to go (security and all), so I have switched to using the authlib library which also made my code somewhat simpler:

from authlib.jose import jwt
jwt_message = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJQb3J0YmFzZSBDY..."
with open(pemfile_name, "r") as fh_pemfile:
    keystring = fh_pemfile.read()
    jwt_payload = jwt.decode(jwt_message, keystring)
Colcannon answered 4/6 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.