Skip to content

Commit

Permalink
feat(option): add internaloption to force use of certain credential (#…
Browse files Browse the repository at this point in the history
…1162)

A new internaloption added that forces the client to use a certain credential. This ensures that if a user directly passes in their own credentials, we can capture and use these credentials.

This is part of the effort to improve Signed URLs in the Go Storage Client.
  • Loading branch information
BrennaEpp authored Aug 31, 2021
1 parent 92c1889 commit 62f4bc9
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 0 deletions.
3 changes: 3 additions & 0 deletions internal/creds.go
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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, "")
}
}

0 comments on commit 62f4bc9

Please sign in to comment.