lepture / authlib

The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.
https://authlib.org/
BSD 3-Clause "New" or "Revised" License
4.58k stars 458 forks source link

Issue using Python 3.13 #681

Closed erikpragt-connectid closed 1 month ago

erikpragt-connectid commented 1 month ago

Describe the bug

A clear and concise description of what the bug is.

Error Stacks

../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/authlib/jose/__init__.py:14: in <module>
    from .rfc7517 import Key, KeySet, JsonWebKey
../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/authlib/jose/rfc7517/__init__.py:10: in <module>
    from ._cryptography_key import load_pem_key
../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/authlib/jose/rfc7517/_cryptography_key.py:1: in <module>
    from cryptography.x509 import load_pem_x509_certificate
../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/cryptography/x509/__init__.py:7: in <module>
    from cryptography.x509 import certificate_transparency, verification
../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/cryptography/x509/certificate_transparency.py:11: in <module>
    from cryptography.hazmat.bindings._rust import x509 as rust_x509
E   pyo3_runtime.PanicException: Python API call failed

To Reproduce

The only thing I'm doing is importing a library:

from authlib.jose import JsonWebSignature

Expected behavior

It shouldn't fail (this code works in 3.12)

Environment:

lepture commented 1 month ago

According to your error stack, it seems cryptography's issue. Can you upgrade cryptography?

Also, if you want to use the jose module, I suggest that you using https://jose.authlib.org/en/migrations/authlib/

erikpragt-connectid commented 1 month ago

Hi @lepture , the only dependencies in my project I have are these:

[tool.poetry.dependencies]
python = "^3.12"
requests = "^2.32.3"
authlib = "^1.3.2"

I've now added cryptography version 43.0.1, but I'm still getting a similar error:

../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/authlib/jose/__init__.py:14: in <module>
    from .rfc7517 import Key, KeySet, JsonWebKey
../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/authlib/jose/rfc7517/__init__.py:10: in <module>
    from ._cryptography_key import load_pem_key
../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/authlib/jose/rfc7517/_cryptography_key.py:1: in <module>
    from cryptography.x509 import load_pem_x509_certificate
../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/cryptography/x509/__init__.py:7: in <module>
    from cryptography.x509 import certificate_transparency, verification
../../../.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/cryptography/x509/certificate_transparency.py:11: in <module>
    from cryptography.hazmat.bindings._rust import x509 as rust_x509
E   ImportError: /home/runner/.cache/pypoetry/virtualenvs/rp-python-sdk-V_ZVmfOb-py3.13/lib/python3.13/site-packages/_cffi_backend.cpython-313-x86_64-linux-gnu.so: undefined symbol: **_PyErr_WriteUnraisableMsg**

I saw the jose module, but after reading the documentation, it wasn't clear to me why I'd use that, why it exists, how it's different. I can give it a go though.

erikpragt-connectid commented 1 month ago

I've migrated the code now to jose, and that gave some issues. It seems the OctKey doesn't like it when my key looks like this:

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhki.........4XiTRA=
-----END PRIVATE KEY-----

This wasn't an issue with the old code. Another issue I ran into, which I'm not sure how to fix, is how to use PS256?

My new code looks like this:

    cleaned_key = config.signing_key.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").strip()
    key = OctKey.import_key(cleaned_key)
    header = {'alg': 'PS256', 'kid': config.signing_kid}
    client_assertion_jwt = jws.serialize_compact(header, json.dumps(client_assertion_payload), key)

And it's throwing an error:

Algorithm of "PS256" is not allowed
erikpragt-connectid commented 1 month ago

Okay, after reading this: https://jose.authlib.org/en/guide/algorithms/, I've given it another shot:

Now with using RSA Key instead of OctKey:

    cleaned_key = config.signing_key.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").strip()
    key = RSAKey.import_key(cleaned_key)
    header = {'alg': 'PS256', 'kid': config.signing_kid}
    client_assertion_jwt = jws.serialize_compact(header, json.dumps(client_assertion_payload), key)

Here, I'm getting:

Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters). Details: ASN.1 parsing error: unexpected tag (got Tag { value: 13, constructed: false, class: Application }

If I remove that cleaning part, I'm getting this:

    key = RSAKey.import_key(config.signing_key)
    header = {'alg': 'PS256', 'kid': config.signing_kid}
    client_assertion_jwt = jws.serialize_compact(header, json.dumps(client_assertion_payload), key)

I'm getting:

Algorithm of "PS256" is not allowed

Any suggestion would be appreciated.

erikpragt-connectid commented 1 month ago

Ah, this seems to be caused by user error: I was using the default registry, and I've updated to a new registry, which made things pass:

    # See https://jose.authlib.org/en/guide/registry/
    registry = JWSRegistry(algorithms=["PS256"])

    key = RSAKey.import_key(config.signing_key)
    header = {'alg': 'PS256', 'kid': config.signing_kid}
    client_assertion_jwt = jws.serialize_compact(header, json.dumps(client_assertion_payload), key, registry = registry)
erikpragt-connectid commented 1 month ago

Unfortunately, the code still doesn't work with Python 3.13.

I have this as my dependencies:

[tool.poetry.dependencies]
python = "^3.12"
requests = "^2.32.3"
authlib = "^1.3.2"
cryptography = "^43.0.1"
joserfc = "^1.0.0"

And with the above code, I'm getting this error:

undefined symbol: _PyErr_WriteUnraisableMsg

Turns out, this is caused by an older version of CFFI. I was using 1.16.0, when I explicitly use CFFI 1.17.1, this fixes the issue. See https://github.com/python-cffi/cffi/issues/23.

I can confirm our code now works on 3.12 and 3.13.