RS256 Token Validation & Decoding using Public Key Not Working "ValueError: Could not deserialize key data."
See original GitHub issueI’m trying to validate Google’s ID Tokens for user authentication on a web app. The id token can be decoded fine if I disable verification, but won’t verify when I pass it the RSA256 Public Key. The Public Key in question is Base64urlUInt-Encoded (RFC 7518 Specification).
The Entire Public Key Response
{
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"kid": "8c9eb968f73744eaed421e48010142bce51a067f",
"n": "uweJ3hFY9wqZ6ZG-iSNhQwHtKCGl8G_jcQgGPjOrS-Rum3dyDjicqkAyfS8XDn480KD_TZ5m-lqBjqfimePu2_cH4URDPIwsqSzJI2_piEhaqnXRptIe5YB5imAL6iETKaOPjw284Fc7EdHK-ekHMn3AXjsy9AIErwAVw4-4ZXXwHbyQXJy1DyUB4ZzxiEvw_qkQmLdltmrNkLOw-Xh-C9UkTZ9NA58bYPBnxLwnAu_ggw_g_-hCAs6OvXZbAfFHhIGBLyjtdDLVrfXo1112QREB9d5sEds0bKZtJcD9afl4E7Ht6G-g3jNP2clAu6-6B-cIe4-j8Ph1uJDPkAmDfw",
"e": "AQAB"
}
According to the Specification I linked above, the “n” parameter is the Modulus, and the “e” parameter is the exponent. I’ve tried absolutely every combination of decoding these to common Base64 format, but no matter what I do, pyJWT doesn’t like it.
Expected Result
A Verified, decoded JSON data packet.
Actual Result
Traceback (most recent call last):
File "/anaconda3/lib/python3.6/site-packages/jwt/algorithms.py", line 205, in prepare_key
key = load_pem_private_key(key, password=None, backend=default_backend())
File "/anaconda3/lib/python3.6/site-packages/cryptography/hazmat/primitives/serialization.py", line 20, in load_pem_private_key
return backend.load_pem_private_key(data, password)
File "/anaconda3/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1015, in load_pem_private_key
password,
File "/anaconda3/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1234, in _load_key
self._handle_key_loading_error()
File "/anaconda3/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1292, 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 "<stdin>", line 1, in <module>
File "/anaconda3/lib/python3.6/site-packages/jwt/api_jwt.py", line 93, in decode
jwt, key=key, algorithms=algorithms, options=options, **kwargs
File "/anaconda3/lib/python3.6/site-packages/jwt/api_jws.py", line 157, in decode
key, algorithms)
File "/anaconda3/lib/python3.6/site-packages/jwt/api_jws.py", line 221, in _verify_signature
key = alg_obj.prepare_key(key)
File "/anaconda3/lib/python3.6/site-packages/jwt/algorithms.py", line 207, in prepare_key
key = load_pem_public_key(key, backend=default_backend())
File "/anaconda3/lib/python3.6/site-packages/cryptography/hazmat/primitives/serialization.py", line 24, in load_pem_public_key
return backend.load_pem_public_key(data)
File "/anaconda3/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1041, in load_pem_public_key
self._handle_key_loading_error()
File "/anaconda3/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1292, in _handle_key_loading_error
raise ValueError("Could not deserialize key data.")
ValueError: Could not deserialize key data.
Reproduction Steps
import jwt
IDjwt = <my id_token here> # Decoding this with verify=False works correctly, so the problem isn't with the ID Token
GoogPubKey = b'uweJ3hFY9wqZ6ZG-iSNhQwHtKCGl8G_jcQgGPjOrS-Rum3dyDjicqkAyfS8XDn480KD_TZ5m-lqBjqfimePu2_cH4URDPIwsqSzJI2_piEhaqnXRptIe5YB5imAL6iETKaOPjw284Fc7EdHK-ekHMn3AXjsy9AIErwAVw4-4ZXXwHbyQXJy1DyUB4ZzxiEvw_qkQmLdltmrNkLOw-Xh-C9UkTZ9NA58bYPBnxLwnAu_ggw_g_-hCAs6OvXZbAfFHhIGBLyjtdDLVrfXo1112QREB9d5sEds0bKZtJcD9afl4E7Ht6G-g3jNP2clAu6-6B-cIe4-j8Ph1uJDPkAmDfw'
#Convert to Base64 (replace '-', '_' with '+', '/', respectively, and pad with '=' to make multiple of 4)
GoogPubKey = GoogPubKey.replace(b'-', b'+')
GoogPubKey = GoogPubKey.replace(b'_', b'/')
GoogPubKey += b'=='
len(GoogPubKey) % 4 # 0
GoogPubKey = b'-----BEGIN PUBLIC KEY-----\n' + GoogPubKey + b'\n-----END PUBLIC KEY-----'
decoded = jwt.decode(IDjwt, GoogPubKey, algorithms='RS256')
Again, I’ve tried over a dozen different ways of using this RSA Public Key Google supplies, but nothing works (Using Base64url like they provide, using or not using the ‘BEGIN PUBLIC KEY’ prefix/suffix, type bytes or str, adding the “AQAB” prefix in multiple places, nothing works)
Any help would be greatly appreciated!! Thank you
System Information
$ python -m jwt.help
{
"cryptography": {
"version": "2.1.4"
},
"implementation": {
"name": "CPython",
"version": "3.6.4"
},
"platform": {
"release": "17.4.0",
"system": "Darwin"
},
"pyjwt": {
"version": "1.6.4"
}
}
Issue Analytics
- State:
- Created 5 years ago
- Reactions:13
- Comments:19 (2 by maintainers)
Top GitHub Comments
Try something like this:
just fyi, a simpler approach also worked for me;