如何使用 Google 的公钥手动验证 JWT 的签名?

问题描述

我正在 Go 脚本中实现 Google 登录,但我一直在尝试验证 ID 令牌是否已由 Google 签名。

具体来说,我正在尝试做 here 中的第一个要点。

我已经获得了令牌并将其拆分为标头、有效载荷和签名。但是我不知道如何使用谷歌的公钥来验证签名。

我看到生成签名涉及 HMACSHA256 algorithm,但我不太清楚如何处理 Google 提供的 JWK 或 PEM 密钥。由于某些限制,我目前正在手动执行此操作。

有人知道我如何验证签名吗?

解决方法

https://github.com/googleapis/google-api-php-client/blob/2fb6e702aca5d68203fa737f89f6f774022494c6/src/AccessToken/Verify.php#L90上的php例子, Google API 似乎使用 RS256(带有 SHA-256 的 RSA 签名)对令牌进行签名。

以下代码应验证签名并解析令牌。 无需在代码中拆分令牌。 “github.com/pascaldekloe/jwt”包中的 jwt.RSACheck(token []byte,key *rsa.PublicKey) (*jwt.Claims,error) 将为您完成所有繁重的工作。

keyLocation 是本地存储的 Google 公钥

package main

import "github.com/pascaldekloe/jwt"

//jwtValidator verifies and parses the JWT Token
func jwtValidator(token string,keyLocation string) (j *jwtToken,err error) {
    token := []byte(token)

    pubK,err := rsaPublicKey(keyLocation)
    if err != nil {
        return
    }

    // parses the token only if signature is valid
    claims,err := jwt.RSACheck(token,pubK)
    if err != nil {
        err = fmt.Errorf("token signature invalid %s",err)
        return
    }
    if !claims.Valid(time.Now()) {
        err = fmt.Errorf("token time constraints exceeded")
        return
    }

    j = &jwtToken{
        id:      claims.ID,issuer:  claims.Issuer,issued:  claims.Issued,subject: claims.Subject,expires: claims.Expires,}

    return
}