Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(option): add internaloption to force use of certain credential #1162

Merged
merged 10 commits into from Aug 31, 2021
3 changes: 3 additions & 0 deletions internal/creds.go
Expand Up @@ -31,6 +31,9 @@ func Creds(ctx context.Context, ds *DialSettings) (*google.Credentials, error) {
}

func baseCreds(ctx context.Context, ds *DialSettings) (*google.Credentials, error) {
if ds.InternalCredentials != nil {
return ds.InternalCredentials, nil
}
if ds.Credentials != nil {
return ds.Credentials, nil
}
Expand Down
59 changes: 59 additions & 0 deletions internal/creds_test.go
Expand Up @@ -236,3 +236,62 @@ func TestQuotaProjectFromCreds(t *testing.T) {
t.Errorf("QuotaProjectFromCreds(quotaProjectJSON): want %q, got %q", want, got)
}
}

func TestCredsWithCredentials(t *testing.T) {
tests := []struct {
name string
ds *DialSettings
want string
}{
{
name: "only normal opt",
ds: &DialSettings{
Credentials: &google.Credentials{
TokenSource: oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: "normal",
}),
},
},
want: "normal",
},
{
name: "normal and internal creds opt",
ds: &DialSettings{
Credentials: &google.Credentials{
TokenSource: oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: "normal",
}),
},
InternalCredentials: &google.Credentials{
TokenSource: oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: "internal",
}),
},
},
want: "internal",
},
{
name: "only internal creds opt",
ds: &DialSettings{
InternalCredentials: &google.Credentials{
TokenSource: oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: "internal",
}),
},
},
want: "internal",
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
creds, err := Creds(context.Background(), tc.ds)
if err != nil {
t.Fatalf("got %v, want nil error", err)
}
if tok, _ := creds.TokenSource.Token(); tok.AccessToken != tc.want {
t.Fatalf("tok.AccessToken = %q, want %q", tok.AccessToken, tc.want)
}
})
}
}
1 change: 1 addition & 0 deletions internal/settings.go
Expand Up @@ -29,6 +29,7 @@ type DialSettings struct {
Credentials *google.Credentials
CredentialsFile string // if set, Token Source is ignored.
CredentialsJSON []byte
InternalCredentials *google.Credentials
UserAgent string
APIKey string
Audiences []string
Expand Down
13 changes: 13 additions & 0 deletions option/internaloption/internaloption.go
Expand Up @@ -6,6 +6,7 @@
package internaloption

import (
"golang.org/x/oauth2/google"
"google.golang.org/api/internal"
"google.golang.org/api/option"
)
Expand Down Expand Up @@ -121,3 +122,15 @@ type enableJwtWithScope bool
func (w enableJwtWithScope) Apply(o *internal.DialSettings) {
o.EnableJwtWithScope = bool(w)
}

// WithCredentials returns a client option to specify credentials which will be used to authenticate API calls.
// This credential takes precedence over all other credential options.
func WithCredentials(creds *google.Credentials) option.ClientOption {
return (*withCreds)(creds)
}

type withCreds google.Credentials

func (w *withCreds) Apply(o *internal.DialSettings) {
o.InternalCredentials = (*google.Credentials)(w)
}
29 changes: 29 additions & 0 deletions option/internaloption/internaloption_test.go
@@ -0,0 +1,29 @@
// Copyright 2021 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package internaloption

import (
"testing"

"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/internal"
)

func TestWithCredentials(t *testing.T) {
want := "fakeToken"
fakeCreds := &google.Credentials{
TokenSource: oauth2.StaticTokenSource(&oauth2.Token{AccessToken: want}),
}
opt := WithCredentials(fakeCreds)
ds := &internal.DialSettings{}
opt.Apply(ds)
if ds.InternalCredentials == nil || ds.InternalCredentials.TokenSource == nil {
t.Errorf("ds.InternalCredentials should be initialized")
}
if tok, err := ds.InternalCredentials.TokenSource.Token(); err != nil || tok.AccessToken != "fakeToken" {
t.Errorf("ts.Token() = %q, want %q", tok.AccessToken, "")
}
}