Como verifico manualmente a assinatura de um JWT usando a chave pública do Google?

Jan 21 2021

Estou implementando o login do Google em um script Go e estou tentando verificar se o token de ID foi assinado pelo Google.

Especificamente, estou tentando fazer o primeiro ponto aqui .

Eu obtive o token e o dividi em seu cabeçalho, carga útil e assinatura. Mas não sei como usar a chave pública do Google para verificar a assinatura.

Eu vi que a geração de assinatura envolve um algoritmo HMACSHA256 , mas não sei bem o que fazer com as chaves JWK ou PEM que o Google fornece. Atualmente estou fazendo isso manualmente devido a certas restrições.

Alguém sabe como posso verificar a assinatura, por favor?

Respostas

2 yebowhatsay Jan 21 2021 at 17:20

Olhando para o exemplo de php em https://github.com/googleapis/google-api-php-client/blob/2fb6e702aca5d68203fa737f89f6f774022494c6/src/AccessToken/Verify.php#L90, parece que a API do Google assina os tokens usando RS256 (Assinatura RSA com SHA-256).

O código a seguir deve verificar a assinatura e analisar o token. Não há necessidade de dividir o token em seu código. jwt.RSACheck (token [] byte, chave * rsa.PublicKey) (* jwt.Claims, error) no pacote "github.com/pascaldekloe/jwt" faria todo o trabalho pesado para você.

keyLocation é a chave pública do Google armazenada localmente

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
}