mpdavis / python-jose

A JOSE implementation in Python
MIT License
1.54k stars 235 forks source link

cryptography backend always throws JWSSignatureError, but native backend works #203

Open cloudspeak opened 3 years ago

cloudspeak commented 3 years ago

I am unable to successfully validate any tokens when the cryptography backend is installed. Consider this example:

    from jose import jwt

    key = {
        "p": "-grGsVMl5QibKa90qaoxToi5Y3ifyJ7qIKG0FowD7AhO6FSYIN1sdQBfoJvI1w7doWtzhgbui5aaVELWWh85QXYJY44OD5wshLEEHl5-RwQXLbme0hKKJ8lJRxGLZ5Njuqi0Q9lybY_jCzyqomO8MDpIC6lB4Y-Ho5OYiwfvrcM",
        "kty": "RSA",
        "q": "kPVfnUuoLlE5FISYCXb5cH-MKRsyhl_rLwPxfMB5uo51R5MVVs5QZ41A2v_aD9Gj6dMRtCjPH0NOdNWA8XO8vPHIONWFrwIyurby52LK7dScGE3kBajaa8sni-L_xwNRU3XuLC8epJY77j9KQTjpj7kYPQQRcj5uoI0OMYdIwjk",
        "d": "aLAOhM33zOvXKY3WjxBTWwAO9itNGXzhgNESUZ2zBKdDPuiBOttgBUHC-1UCLDQTIP1TGgr54KeU4-9dWfxvht9S4ao-_0mhG7j4YyCd9ylW1VDcKKzAu23N5JeFhWM3T6LW8-wovU9ck46aduVtOWq7SYNwP_DVF2SKnzgrIPIxe-VpJlUhKDGaIS4v0oWPJXO-EhWkfLw3ZRej7uHxhCcFHdvkSDnoc8sgH1rYQGrRFoK_KUvASK6dsj4xAi3vGyrMDsi5tLGlzrM6Epld2WQZlgWuVn_bDo6_5RcbDoymrjxcZ7t6cTztidYKmap8RuTmJUlTpy8zrOryzM-MYQ",
        "e": "AQAB",
        "use": "sig",
        "kid": "secret-key",
        "qi": "Ww71WmxctPV77Q2OSrwesBF11A0o7d7GeoV8hyt4UrS5v2XtMd8is2hyieCeFypNtqrC_8MsJVSX4Z0DqgXpUTkRmT5k9bGVB0_SSSWlaClxzQgnrLUD__UWS-l-gpZtdG29AHVCZWhKyDtpQSWwGKxd0lc8TTxVVObvjR6XY3Y",
        "dp": "vLUnUasUHW_KUsKVhHrq7X9okvb1eF7fCjOgC6guSZPXoaY-jgculHrssPUBtbUFdY73x_4xSG4oGVG8HpYUCyB_Y4BRglx2iMpj9luQaB5hM-Q0Rg0x8WcLg7RtBoWJLdWm_tH8d02xp8hoa1hkLe2-c_aQvyAo2T5KURtzOys",
        "alg": "RS256",
        "dq": "HFab1phPzJ48VnKFdnQ313JX6EFU40glJg_TSdwm7_2hl9h9N3cl6NiIcUfLTYRiUvfcYigINchmshh7GLjTkOyDg_jaJZh8alwRqIJ7wXrq-SVhCmo0KRaSKJq7_h_76iEH6sNbbjmghbcBwTZrEpnQzzzYXEkwP1rUB4K3CqE",
        "n": "jZW5d4i2-TmzV3ANK3j7MGDAVNWopU15W5Z8HuUHWw7YMFOuqSQunq_3BlmbOrSGTC6jXaf3BF8UZm08j13thvkBDR5A50-YOrcASSnLMNI1I52pLY3gB1iaBT-FwgZNCkVTXlviVr8E-IaOZLElzx9EoGIEpUxCWs_Bo5sWX7KF81k6vp7Ht4qnTlQb6jM9SfxDCcb0C-2U4aUofcpZsPDYWbWoIGALS4Od0p2VzSJHk7ORP9Ox6VcYUobLmjmBexG7H3Es_IgQ8yzsR6Nrh101lDZxZGJVjMeKVdbdryT_DAB6Iol0LsKyTlzcAMEKhWxrQpNvco-yh99WGeN2aw",
    }

    token = jwt.encode(
        headers={
            "alg": key.get("alg"),
            "kid": key.get("kid"),
        },
        claims={},
        algorithm=key.get("alg"),
        key=key,
    )

    jwt.decode(
        token=token,
        key=key,
        algorithms=[key.get("alg")],
    )

Clearly, the decode method should not fail in this case, and when I install python-jose by itself, it does not. However, if I install the cryptography package with poetry:

poetry add cryptography

The decode method now throws a JWSSignatureError with the message Signature verification failed. even though I haven't changed the code at all. I tried a few different encryption algorithms and it seems both RSA and EC are affected, but oct is not (although this is not sufficient for my purposes).

Frustratingly, I don't actually care which backend is used, but I have some other packages which require cryptography so I can't stop python-jose from using it.

As far as I can see this is a bug. Can anyone see something I'm doing wrong or have any ideas of a workaround? Many thanks.

Here is some detail about my environment:

mpdavis commented 3 years ago

Hey @cloudspeak,

It looks like you are passing in a private key to the verify function and we aren't properly extracting the public key information from that JWK in some of our backends, including the cryptography backend. I am able to get it to work by simply removing some of the private key material.

del key['d']

jwt.decode(
    token=token,
    key=key,
    algorithms=[key.get("alg")],
)

Most of the time, users are verifying tokens with only a public key, and not the full key material. However, I agree that it is a bug. All of the data necessary to verify the token is being provided in the key, we just aren't properly extracting it.

cloudspeak commented 3 years ago

Thanks @mpdavis, I have verified this was exactly my problem.