Jak ręcznie zweryfikować podpis tokena JWT za pomocą klucza publicznego Google?

Jan 21 2021

Implementuję logowanie Google w skrypcie Go i utknąłem, próbując sprawdzić, czy token identyfikacyjny został podpisany przez Google.

W szczególności staram się tutaj opisać pierwszy punkt .

Uzyskałem token i podzieliłem go na nagłówek, ładunek i podpis. Ale nie wiem, jak użyć klucza publicznego Google do zweryfikowania podpisu.

Widziałem, że generowanie podpisu obejmuje algorytm HMACSHA256 , ale nie bardzo wiem, co zrobić z kluczami JWK lub PEM, które dostarcza Google. Obecnie robię to ręcznie z powodu pewnych ograniczeń.

Czy ktoś wie, jak mogę zweryfikować podpis?

Odpowiedzi

2 yebowhatsay Jan 21 2021 at 17:20

Patrząc na przykład php na https://github.com/googleapis/google-api-php-client/blob/2fb6e702aca5d68203fa737f89f6f774022494c6/src/AccessToken/Verify.php#L90wygląda na to, że Google API podpisuje tokeny za pomocą RS256 (podpis RSA z SHA-256).

Poniższy kod powinien zweryfikować podpis i przeanalizować token. Nie ma potrzeby dzielenia tokena w kodzie. jwt.RSACheck (token [] bajt, klucz * rsa.PublicKey) (* jwt.Claims, błąd) w pakiecie „github.com/pascaldekloe/jwt” zrobi wszystko za Ciebie.

keyLocation to publiczny klucz Google przechowywany lokalnie

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
}