使用 JWK/JWT 进行用户身份验证时令牌验证失败

Dar*_*der 3 python rsa oauth-2.0 jwt jwk

我正在尝试使用 python 中的公钥来验证 idToken。

我首先将 JWK 令牌转换为 PEM,但当我调用“解码”函数时,我看到“签名验证失败”异常。我缺少什么?

# Long string goes here - this is the token to verify
myToken = 'ezFraWQiXXX.YYYYYYYY.ZZZZZZZZ'

# JWK Token
webkey = {
      "alg": "RS256",
      "e": "AQAB",
      "kid": "d9FzOfniXuHf2sF3opIKZb0sW8Nuaa0d5d+AXXXXXXXX=",
      "kty": "RSA",
      "n": "nQwBvRlZKdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4HcenyO_WASyjr6korLEHxh8XXXXXXXXXXXX",
      "use": "sig"
    }

# Converting JWK to PEM
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(webkey)
pubk_bytes = public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo)


# This is where I get the "signature verification failed" exception
claim = jwt.decode(myToken, pubk_bytes, algorithms=['RS256']) # <<-- ideally this should decode the token for me

Run Code Online (Sandbox Code Playgroud)

Gar*_*her 8

看起来您正在使用PyJWT,这是安全库的一个不错的选择。理想情况下,让库从授权服务器的 JWKS 端点下载令牌签名公钥,以获得最干净、最简单的代码:

import jwt
from jwt import PyJWKClient

// The client will read the JWT header to get the kid field,
// then download token signing public keys and return that matching the kid.
// This key will then be cached for future JWTs with the same kid.
// The client will reliably handle new kids if keys are recycled.
jwks_client = PyJWKClient(url)
signing_key = jwks_client.get_signing_key_from_jwt(access_token_jwt)

// It is recommended to verify the signature, expiry, issuer and audience.
// As a best practice, the API should also specify the algorithms it expects
// to receive in JWT signatures.
claims = jwt.decode(
  access_token_jwt,
  signing_key.key,
  algorithms=["RS256"],
  issuer="my-issuer",
  audience="my-audience")
Run Code Online (Sandbox Code Playgroud)

您应该能够将 JWK 直接发送到库中,而不是处理 RSA 或字节转换。有关一些示例,请参阅pyJWT 文档。要了解更多安全背景,您可能还会发现有关JWT 最佳实践的Curity 文章很有用。