从断言中解码 JWT - Google 登录

Posted

技术标签:

【中文标题】从断言中解码 JWT - Google 登录【英文标题】:JWT decode from assertion - Google sign in 【发布时间】:2019-03-28 13:32:36 【问题描述】:

我正在尝试在 Actions on Google 中实现帐户关联(使用 this)

我被困在 处理自动链接 步骤中。当我尝试使用指定的python-jose 库over here! 对其进行解码时,我从请求中得到assertion

from jose import jwt
key = "728f4016652079b9ed99861bb09bafc5a45baa86" # PUBLIC KEY OF GOOGLE from https://www.googleapis.com/oauth2/v3/certs
encoded = "ENCODED_ASSERTION"
decoded = jwt.decode(encoded, key, algorithms='RS256')
print (decoded)

当我运行这段代码时,它会显示

Traceback (most recent call last):

File "/Users/jay.patel/env372/lib/python3.7/site-packages/jose/backends/pycrypto_backend.py", line 72, in __init__
    self.prepared_key = RSA.importKey(key)
  File "/Users/jay.patel/env372/lib/python3.7/site-packages/Crypto/PublicKey/RSA.py", line 757, in import_key
    raise ValueError("RSA key format is not supported")
ValueError: RSA key format is not supported

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/jay.patel/PycharmProjects/Prac/jwt.py", line 19, in <module>
    decoded = jwt.decode(encoded, key, algorithms='RS256')
  File "/Users/jay.patel/env372/lib/python3.7/site-packages/jose/jwt.py", line 135, in decode
    payload = jws.verify(token, key, algorithms, verify=verify_signature)
  File "/Users/jay.patel/env372/lib/python3.7/site-packages/jose/jws.py", line 77, in verify
    _verify_signature(signing_input, header, signature, key, algorithms)
  File "/Users/jay.patel/env372/lib/python3.7/site-packages/jose/jws.py", line 264, in _verify_signature
    if not _sig_matches_keys(keys, signing_input, signature, alg):
  File "/Users/jay.patel/env372/lib/python3.7/site-packages/jose/jws.py", line 212, in _sig_matches_keys
    key = jwk.construct(key, alg)
  File "/Users/jay.patel/env372/lib/python3.7/site-packages/jose/jwk.py", line 61, in construct
    return key_class(key_data, algorithm)
  File "/Users/jay.patel/env372/lib/python3.7/site-packages/jose/backends/pycrypto_backend.py", line 74, in __init__
    raise JWKError(e)
jose.exceptions.JWKError: RSA key format is not supported

我做错了什么??我刚刚使用了 RS256,因为它是在 Google 的公钥中指定的(提供 JWK 或 PEM 格式)

附言 当我尝试使用RS256 算法解码断言here 时,它显示无效签名错误,如下图所示。

编辑 我知道我传递了错误的密钥,所以现在我正在使用此代码从证书生成公钥,但它给了我这个错误。

initializer for ctype 'char' must be a bytes of length 1, not int 

这是我的代码

from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend

certificate_text = open('certificate.txt', 'r').read()
certBytes = list(certificate_text.encode())
certificate = load_pem_x509_certificate(certBytes, default_backend())
publicKey = certificate.public_key()

这就是我的 certificate.txt 的样子:

-----BEGIN CERTIFICATE-----
MIIDJjCCAg6gAwIBAgIIHiSmgNCe4EIwDQYJKoZIhvcNAQEFBQAwNjE0MDIGA1UE
AxMrZmVkZXJhdGVkLXNpZ25vbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTAe
Fw0xODEwMjQxNDQ5MTFaFw0xODExMTAwMzA0MTFaMDYxNDAyBgNVBAMTK2ZlZGVy
YXRlZC1zaWdub24uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCPeue6aABtdQzCrAvfWU1Vi69YZuuJPu7L
sKBN6rB80t/pD1MxCUOJ2sUVIuBJ7YGJ+MSzBLoHiqmxcyWsyhKjMjBse5KShBl1
jabm8URlGTIcHiYApm7NSLlcfktWWVu/ZMGnoqyMlZJJbkGfJ6f2kh5qYd04Ohf8
8R0GGaqScNRFG66rcFvchWe50Y/wkJsdNnzplLZpLaGlgrd4Dx2+nXnkrWMowAb1
Yfz2OGR4VHrs6r2YP7IZkNo0I3yc5lHkjLD5ZAmjn6KMQByQdefVJ1gaNCCb/Z+8
QGx/SAkSObHYOs15pxkvINQD90H0kjLlmt8VnQf2XQiRKCCBRJqRAgMBAAGjODA2
MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsG
AQUFBwMCMA0GCSqGSIb3DQEBBQUAA4IBAQAXw0JJPtxs1hanLTxSFI21ib4BDUuI
+Aksnz1azijb6cKXVJAtDMQABpH2u6VTcnnGJ/nIQ4KeJHxMDL2w6wvViz9wwRH3
lru5D6Jks8IShBSeM80IOwrfxodEfju47B+G3Zxg/1qQ4QV0S3C+oMmcqQqHFK+l
Z6glTHJrNLjH+xtiwav6jIGUhDByHiRdEOp1hYBWt7tpbeLb4Mhxyk0schaf6o47
iF3bur6WaEPUI8rUBDv0rXKS3leN3AJmmEEnRZPCoBrNDg1Esxxy/VNLHhhKRHoc
+/K4sQuHeICO1a+yetfXIO6qa3rOOxEuL9ZpWvpSDqcRbYecDqa9CiZK
-----END CERTIFICATE-----

我做错了什么? (我已经从here 复制了其中一个证书并从中删除了\n

【问题讨论】:

【参考方案1】:

您在处理 JWT 方面存在一些问题。

首先,您所说的“钥匙”实际上是“孩子”或“钥匙 ID”。它引用了您应该使用的 https://www.googleapis.com/oauth2/v3/certs 中的哪个键。这些密钥经常轮换,因此您有时需要重新获取它们,然后使用“孩子”来确定使用哪个密钥对其进行签名。没有提供“钥匙”本身,因为那是不安全的(想象一下发送一个上锁的玻璃盒,钥匙贴在它的顶部)。

我怀疑错误信息具有欺骗性。不是不支持 RSA,而是不支持您提供的 RSA 密钥格式。这是有道理的——你没有提供密钥。 The documentation 表示支持 RS256。虽然没有示例 the documentation on verify() 表示密钥可以是 JWK or JWK Set,这是 Google 在证书 URL 中提供的,因此您应该能够提供这些。

jwt.io 手动解码说签名无效的原因是......好吧......因为鉴于您提供的信息,它是。你没有在签名部分(蓝色部分)给它一个公钥,它可以用来验证令牌的其他部分,所以它认为它是无效的。

【讨论】:

是的,我一直在冲浪,我知道我传递了错误的密钥,但我被困在从证书生成公钥,我累了 cryptography, @987654327 @ 但他们都给了我同样的错误initializer for ctype 'char' must be a bytes of length 1, not int 我已经更新了我的问题,请告诉我我做错了什么吗? 您是否尝试仅使用 Google 发送的 JWK 或 JWK 集? (关于 Jose 的文档表明它应该可以工作。) 我可以使用这个命令生成公钥openssl x509 -pubkey -noout -in certificate.txt &gt; certpubkey.pem 您从哪里获得 PEM 密钥被接受的信息?

以上是关于从断言中解码 JWT - Google 登录的主要内容,如果未能解决你的问题,请参考以下文章

无法解码 Firebase JWT

为啥jwt.io不能解码google JWT token

解码时jwt签名异常

B2C 返回的 Token 没有被 JWT.MS 解码

在 Angular 6 中解码 firebase/php-jwt

如何解码我在 Swift 中收到 REST API 的 JWT 令牌?