From 9f3314589c9a9136388751d9adae6b0ed400978a Mon Sep 17 00:00:00 2001 From: Steven Buss Date: Fri, 29 Mar 2019 22:47:46 +0000 Subject: [PATCH] google: Support scopes for ComputeTokenSource Scopes have been added as a query parameter to the metadata server. Change-Id: Ife68db01beeca386e558edd424fa11da508b7287 GitHub-Last-Rev: 1cb4a6ec12f2b17f6a2290a524b18d60246d56ae GitHub-Pull-Request: golang/oauth2#376 Reviewed-on: https://go-review.googlesource.com/c/oauth2/+/170106 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- google/default.go | 3 +-- google/example_test.go | 4 +++- google/google.go | 15 ++++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/google/default.go b/google/default.go index 5087d84..ad2c092 100644 --- a/google/default.go +++ b/google/default.go @@ -73,7 +73,6 @@ func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSourc // 4. On Google Compute Engine, Google App Engine standard second generation runtimes // (>= Go 1.11), and Google App Engine flexible environment, it fetches // credentials from the metadata server. -// (In this final case any provided scopes are ignored.) func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials, error) { // First, try the environment variable. const envVar = "GOOGLE_APPLICATION_CREDENTIALS" @@ -109,7 +108,7 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials id, _ := metadata.ProjectID() return &DefaultCredentials{ ProjectID: id, - TokenSource: ComputeTokenSource(""), + TokenSource: ComputeTokenSource("", scopes...), }, nil } diff --git a/google/example_test.go b/google/example_test.go index 4338ca3..3fc9cad 100644 --- a/google/example_test.go +++ b/google/example_test.go @@ -126,7 +126,9 @@ func ExampleComputeTokenSource() { // Fetch from Google Compute Engine's metadata server to retrieve // an access token for the provided account. // If no account is specified, "default" is used. - Source: google.ComputeTokenSource(""), + // If no scopes are specified, a set of default scopes + // are automatically granted. + Source: google.ComputeTokenSource("", "https://www.googleapis.com/auth/bigquery"), }, } client.Get("...") diff --git a/google/google.go b/google/google.go index df8e87d..6eb2aa9 100644 --- a/google/google.go +++ b/google/google.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "fmt" + "net/url" "strings" "time" @@ -151,14 +152,16 @@ func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oau // from Google Compute Engine (GCE)'s metadata server. It's only valid to use // this token source if your program is running on a GCE instance. // If no account is specified, "default" is used. +// If no scopes are specified, a set of default scopes are automatically granted. // Further information about retrieving access tokens from the GCE metadata // server can be found at https://cloud.google.com/compute/docs/authentication. -func ComputeTokenSource(account string) oauth2.TokenSource { - return oauth2.ReuseTokenSource(nil, computeSource{account: account}) +func ComputeTokenSource(account string, scope ...string) oauth2.TokenSource { + return oauth2.ReuseTokenSource(nil, computeSource{account: account, scopes: scope}) } type computeSource struct { account string + scopes []string } func (cs computeSource) Token() (*oauth2.Token, error) { @@ -169,7 +172,13 @@ func (cs computeSource) Token() (*oauth2.Token, error) { if acct == "" { acct = "default" } - tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token") + tokenURI := "instance/service-accounts/" + acct + "/token" + if len(cs.scopes) > 0 { + v := url.Values{} + v.Set("scopes", strings.Join(cs.scopes, ",")) + tokenURI = tokenURI + "?" + v.Encode() + } + tokenJSON, err := metadata.Get(tokenURI) if err != nil { return nil, err }