¿Cómo verificar un token JWT de AWS Cognito en Go?

Resuelto Lewis Lebentz asked hace 54 años • 7 respuestas

¿Cómo puedo validar y obtener información de un JWT recibido de Amazon Cognito?

Configuré la autenticación de Google en Cognito y configuré el uri de redireccionamiento para acceder a API Gateway, luego recibo un código que PUBLICO en este punto final:

https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html

Para recibir el token JWT, en formato RS256. Ahora estoy luchando por validar y analizar el token en Golang. Intenté analizarlo usando jwt-go, pero parece ser compatible con HMAC de forma predeterminada y leí en alguna parte que recomiendan usar la validación de interfaz en su lugar. Probé algunos otros paquetes y tuve problemas similares.

Encontré esta respuesta aquí: Vaya a Idioma y verifique JWT , pero suponga que el código está desactualizado, ya que solo dicepanic: unable to find key .

jwt.io puede decodificar fácilmente la clave y probablemente también verificarla. No estoy seguro de dónde están las claves públicas/secretas cuando Amazon generó el token, pero según tengo entendido, también necesito usar una URL JWK para validar. Encontré algunas soluciones específicas de AWS, pero todas parecen tener cientos de líneas. Seguramente no es tan complicado en Golang, ¿verdad?

Lewis Lebentz avatar Jan 01 '70 08:01 Lewis Lebentz
Aceptado

Claves públicas para Amazon Cognito

Como ya habrás adivinado, necesitarás la clave pública para verificar el token JWT.

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

Descargue y almacene la clave web JSON pública (JWK) correspondiente para su grupo de usuarios. Está disponible como parte de un conjunto de claves web JSON (JWKS). Puede localizarlo en https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

Analizar claves y verificar token

Esa estructura de archivos JSON está documentada en la web, por lo que podría analizarla manualmente, generar las claves públicas, etc.

Pero probablemente sería más fácil usar una biblioteca, por ejemplo esta: https://github.com/lestrat-go/jwx

Y luego jwt-go para ocuparse de la parte JWT: https://github.com/dgrijalva/jwt-go

Entonces puedes:

  1. Descargue y analice las claves públicas JSON usando la primera biblioteca

     keySet, err := jwk.Fetch(THE_COGNITO_URL_DESCRIBED_ABOVE)
    
  2. Al analizar el token con jwt-go, use el campo "kid" del encabezado JWT para encontrar la clave correcta para usar

     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
    
eugenioy avatar Jul 05 '2019 17:07 eugenioy

Esto es lo que hice sólo con la última versión ( v1.0.8) github.com/lestrrat-go/jwx. Tenga en cuenta que github.com/dgrijalva/jwt-goparece que ya no se mantiene y la gente lo está bifurcando para realizar las actualizaciones que necesitan.

package main

import (
    ...
    "github.com/lestrrat-go/jwx/jwk"
    "github.com/lestrrat-go/jwx/jwt"
)
    ...

    keyset, err := jwk.Fetch("https://cognito-idp." + region + ".amazonaws.com/" + userPoolID + "/.well-known/jwks.json")

    parsedToken, err := jwt.Parse(
        bytes.NewReader(token), //token is a []byte
        jwt.WithKeySet(keyset),
        jwt.WithValidate(true),
        jwt.WithIssuer(...),
        jwt.WithClaimValue("key", value),
    )

    //check err as usual
    //here you can call methods on the parsedToken to get the claim values
    ...

Métodos de reclamación de tokens

James South avatar Jan 29 '2021 00:01 James South