Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration guide for python-jose users #942

Open
lsmith77 opened this issue Feb 3, 2024 · 3 comments
Open

Migration guide for python-jose users #942

lsmith77 opened this issue Feb 3, 2024 · 3 comments
Labels

Comments

@lsmith77
Copy link

lsmith77 commented Feb 3, 2024

It appears that python-jose is unmaintained, itself depends on unmaintaiend projects and now also suffers from dependencies with security vulnerabilities:
mpdavis/python-jose#341

As such I am looking to migrate to this package. Most of the methods appear to be 100% API compatible. There is no get_unverified_claims() but jwt.decode(token, options={"verify_signature": False}) is easy enough to use in its place though having a dedicated function with such a clear name might be a good idea to facilitate defensive coding practices.

Where I am struggeling is that with python-jose I can pass in the RSA key as a dict (containing the n, e etc. values) to jwt.decode() rather than a PEM-formatted public key as expected in this package. I didn't find a function to generate a PEM in this package. Or am I missing something?

@lsmith77
Copy link
Author

lsmith77 commented Feb 5, 2024

I have looked through the python-json code and I think I have a working version to create a PEM from n/e values:

# Copied from https://github.com/mpdavis/python-jose/blob/master/jose/utils.py - MIT License
def int_arr_to_long(arr):
    return int("".join(["%02x" % byte for byte in arr]), 16)


# Copied from https://github.com/mpdavis/python-jose/blob/master/jose/utils.py - MIT License
def base64_to_long(data):
    if isinstance(data, str):
        data = data.encode("ascii")

    # urlsafe_b64decode will happily convert b64encoded data
    _d = base64.urlsafe_b64decode(bytes(data) + b"==")
    return int_arr_to_long(struct.unpack("%sB" % len(_d), _d))


# Inspired by https://github.com/mpdavis/python-jose/blob/master/jose/backends/rsa_backend.py - MIT License
def convert_to_pem(n, e):
    rsa_key = pyrsa.PublicKey(e=base64_to_long(e), n=base64_to_long(n))
    der = rsa_key.save_pkcs1(format="DER")
    return pyrsa_pem.save_pem(der, pem_marker="RSA PUBLIC KEY")

@jpadilla jpadilla added the keep label Feb 6, 2024
@jpmckinney
Copy link

jpmckinney commented Mar 27, 2024

get_unverified_header

from jose import jwt
jwt.get_unverified_header(token)
import jwt
jwt.get_unverified_header(token)

base64url_decode

from jose.utils import base64url_decode

https://github.com/mpdavis/python-jose/blob/4b0701b46a8d00988afcc5168c2b3a1fd60d15d8/jose/utils.py#L72-L77

from jwt.utils import base64url_decode

pyjwt/jwt/utils.py

Lines 28 to 33 in 7b4bc84

rem = len(input_bytes) % 4
if rem > 0:
input_bytes += b"=" * (4 - rem)
return base64.urlsafe_b64decode(input_bytes)

JWTError

jose's JWTError's subclasses are JWTClaimsError and ExpiredSignatureError.

from jose import JWTError

https://github.com/mpdavis/python-jose/blob/4b0701b46a8d00988afcc5168c2b3a1fd60d15d8/jose/exceptions.py#L17

from jwt import InvalidTokenError

class InvalidTokenError(PyJWTError):

pyjwt has ExpiredSignatureError, and multiple errors to cover JWTClaimsError.

@jpmckinney
Copy link

jpmckinney commented Mar 27, 2024

For my needs, I just haven't figured out the replacement for jwk.construct() (docs).

I probably need to do something with PyJWK?

from jose import jwk
key = jwk.construct(data)
key.verify(msg, sig)
import jwt
obj = jwt.PyJWK(data)
# ???

Edit: This seems to work:

import jwt
obj = jwt.PyJWK(data)
alg_obj = obj.Algorithm
prepared_key = alg_obj.prepare_key(obj.key)
alg_obj.verify(msg, prepared_key, sig)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants