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

token verification failing using JWK/JWT for user authentication

我正在尝试使用 python 中的 public 密钥验证 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

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

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")

您应该能够将 JWK 直接发送到库中,而不用处理 RSA 或字节转换。见pyJWT docs for some examples. For further security background, you may also find the Curity article on JWT Best Practices有用。