且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 Go 中从 AWS Cognito 验证 JWT 令牌?

更新时间:2023-02-16 14:54:35

Amazon Cognito 的公钥

正如您已经猜到的,您需要公钥来验证 JWT 令牌.

As you already guessed, you'll need the public key in order to verify the JWT token.

https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html#amazon-cognito-user-pools-using-tokens-step-2

为您的用户池下载并存储相应的公共 JSON Web 密钥 (JWK).它作为 JSON Web 密钥集 (JWKS) 的一部分提供.你可以在https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

Download and store the corresponding public JSON Web Key (JWK) for your user pool. It is available as part of a JSON Web Key Set (JWKS). You can locate it at https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

解析密钥并验证令牌

该 JSON 文件结构记录在网络中,因此您可以手动解析该结构,生成公钥等.

That JSON file structure is documented in the web, so you could potentially parse that manually, generate the public keys, etc.

但是只使用一个库可能会更容易,例如这个:https://github.com/lestrrat-go/jwx

But it'd probably be easier to just use a library, for example this one: https://github.com/lestrrat-go/jwx

然后jwt-go处理JWT部分:https://github.com/dgrijalva/jwt-go

And then jwt-go to deal with the JWT part: https://github.com/dgrijalva/jwt-go

然后你可以:

  1. 使用第一个库下载并解析公钥 JSON

  1. Download and parse the public keys JSON using the first library

 keySet, err := jwk.Fetch(THE_COGNITO_URL_DESCRIBED_ABOVE)

  • 用jwt-go解析token时,使用kid"JWT 标头中的字段以找到要使用的正确密钥

  • When parsing the token with jwt-go, use the "kid" field from the JWT header to find the right key to use

     token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
     if _, ok := token.Method.(*jwt.SigningMethodRS256); !ok {
         return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
     }
     kid, ok := token.Header["kid"].(string)
     if !ok {
         return nil, errors.New("kid header not found")
     }
     keys := keySet.LookupKeyID(kid);
     if !ok {
         return nil, fmt.Errorf("key with specified kid is not present in jwks")
     }
     var publickey interface{}
     err = keys.Raw(&publickey)
     if err != nil {
         return nil, fmt.Errorf("could not parse pubkey")
     }
     return publickey, nil