google: support scopes for JWT access token

This commit is contained in:
Shin Fan
2021-06-14 17:00:17 -07:00
parent f6687ab280
commit ff3df7374f
2 changed files with 99 additions and 5 deletions

View File

@@ -7,6 +7,7 @@ package google
import (
"crypto/rsa"
"fmt"
"strings"
"time"
"golang.org/x/oauth2"
@@ -24,6 +25,24 @@ import (
// optimization supported by a few Google services.
// Unless you know otherwise, you should use JWTConfigFromJSON instead.
func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.TokenSource, error) {
return newJWTSource(jsonKey, audience, nil)
}
// JWTAccessTokenSourceWithScope uses a Google Developers service account JSON
// key file to read the credentials that authorize and authenticate the
// requests, and returns a TokenSource that does not use any OAuth2 flow but
// instead creates a JWT and sends that as the access token.
// The scopes is typically a list of URLs that specifies the scope of the
// credentials.
//
// Note that this is not a standard OAuth flow, but rather an
// optimization supported by a few Google services.
// Unless you know otherwise, you should use JWTConfigFromJSON instead.
func JWTAccessTokenSourceWithScope(jsonKey []byte, scopes []string) (oauth2.TokenSource, error) {
return newJWTSource(jsonKey, "", scopes)
}
func newJWTSource(jsonKey []byte, audience string, scopes []string) (oauth2.TokenSource, error) {
cfg, err := JWTConfigFromJSON(jsonKey)
if err != nil {
return nil, fmt.Errorf("google: could not parse JSON key: %v", err)
@@ -35,6 +54,7 @@ func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.Token
ts := &jwtAccessTokenSource{
email: cfg.Email,
audience: audience,
scopes: scopes,
pk: pk,
pkID: cfg.PrivateKeyID,
}
@@ -47,6 +67,7 @@ func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.Token
type jwtAccessTokenSource struct {
email, audience string
scopes []string
pk *rsa.PrivateKey
pkID string
}
@@ -54,12 +75,14 @@ type jwtAccessTokenSource struct {
func (ts *jwtAccessTokenSource) Token() (*oauth2.Token, error) {
iat := time.Now()
exp := iat.Add(time.Hour)
scope := strings.Join(ts.scopes, " ")
cs := &jws.ClaimSet{
Iss: ts.email,
Sub: ts.email,
Aud: ts.audience,
Iat: iat.Unix(),
Exp: exp.Unix(),
Iss: ts.email,
Sub: ts.email,
Aud: ts.audience,
Scope: scope,
Iat: iat.Unix(),
Exp: exp.Unix(),
}
hdr := &jws.Header{
Algorithm: "RS256",