@@ -16,6 +16,7 @@ import (
1616
1717 "cloud.google.com/go/compute/metadata"
1818 "golang.org/x/oauth2"
19+ "golang.org/x/oauth2/authhandler"
1920)
2021
2122// Credentials holds Google credentials, including "Application Default Credentials".
@@ -41,6 +42,32 @@ type Credentials struct {
4142// Deprecated: use Credentials instead.
4243type DefaultCredentials = Credentials
4344
45+ // CredentialsParams holds user supplied parameters that are used together
46+ // with a credentials file for building a Credentials object.
47+ type CredentialsParams struct {
48+ // Scopes is the list OAuth scopes. Required.
49+ // Example: https://www.googleapis.com/auth/cloud-platform
50+ Scopes []string
51+
52+ // Subject is the user email used for domain wide delegation (see
53+ // https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority).
54+ // Optional.
55+ Subject string
56+
57+ // AuthHandler is the AuthorizationHandler used for 3-legged OAuth flow. Optional.
58+ AuthHandler authhandler.AuthorizationHandler
59+
60+ // State is a unique string used with AuthHandler. Optional.
61+ State string
62+ }
63+
64+ func (params CredentialsParams ) deepCopy () CredentialsParams {
65+ paramsCopy := params
66+ paramsCopy .Scopes = make ([]string , len (params .Scopes ))
67+ copy (paramsCopy .Scopes , params .Scopes )
68+ return paramsCopy
69+ }
70+
4471// DefaultClient returns an HTTP Client that uses the
4572// DefaultTokenSource to obtain authentication credentials.
4673func DefaultClient (ctx context.Context , scope ... string ) (* http.Client , error ) {
@@ -62,7 +89,7 @@ func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSourc
6289 return creds .TokenSource , nil
6390}
6491
65- // FindDefaultCredentials searches for "Application Default Credentials".
92+ // FindDefaultCredentialsWithParams searches for "Application Default Credentials".
6693//
6794// It looks for credentials in the following places,
6895// preferring the first location found:
@@ -81,11 +108,14 @@ func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSourc
81108// 4. On Google Compute Engine, Google App Engine standard second generation runtimes
82109// (>= Go 1.11), and Google App Engine flexible environment, it fetches
83110// credentials from the metadata server.
84- func FindDefaultCredentials (ctx context.Context , scopes ... string ) (* Credentials , error ) {
111+ func FindDefaultCredentialsWithParams (ctx context.Context , params CredentialsParams ) (* Credentials , error ) {
112+ // Make defensive copy of the slices in params.
113+ params = params .deepCopy ()
114+
85115 // First, try the environment variable.
86116 const envVar = "GOOGLE_APPLICATION_CREDENTIALS"
87117 if filename := os .Getenv (envVar ); filename != "" {
88- creds , err := readCredentialsFile (ctx , filename , scopes )
118+ creds , err := readCredentialsFile (ctx , filename , params )
89119 if err != nil {
90120 return nil , fmt .Errorf ("google: error getting credentials using %v environment variable: %v" , envVar , err )
91121 }
@@ -94,7 +124,7 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials
94124
95125 // Second, try a well-known file.
96126 filename := wellKnownFile ()
97- if creds , err := readCredentialsFile (ctx , filename , scopes ); err == nil {
127+ if creds , err := readCredentialsFile (ctx , filename , params ); err == nil {
98128 return creds , nil
99129 } else if ! os .IsNotExist (err ) {
100130 return nil , fmt .Errorf ("google: error getting credentials using well-known file (%v): %v" , filename , err )
@@ -106,7 +136,7 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials
106136 if appengineTokenFunc != nil {
107137 return & DefaultCredentials {
108138 ProjectID : appengineAppIDFunc (ctx ),
109- TokenSource : AppEngineTokenSource (ctx , scopes ... ),
139+ TokenSource : AppEngineTokenSource (ctx , params . Scopes ... ),
110140 }, nil
111141 }
112142
@@ -116,7 +146,7 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials
116146 id , _ := metadata .ProjectID ()
117147 return & DefaultCredentials {
118148 ProjectID : id ,
119- TokenSource : ComputeTokenSource ("" , scopes ... ),
149+ TokenSource : ComputeTokenSource ("" , params . Scopes ... ),
120150 }, nil
121151 }
122152
@@ -125,18 +155,38 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials
125155 return nil , fmt .Errorf ("google: could not find default credentials. See %v for more information." , url )
126156}
127157
128- // CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can
129- // represent either a Google Developers Console client_credentials.json file (as in
130- // ConfigFromJSON), a Google Developers service account key file (as in
131- // JWTConfigFromJSON) or the JSON configuration file for workload identity federation
132- // in non-Google cloud platforms (see
133- // https://cloud.google.com/iam/docs/how-to#using-workload-identity-federation).
134- func CredentialsFromJSON (ctx context.Context , jsonData []byte , scopes ... string ) (* Credentials , error ) {
158+ // FindDefaultCredentials invokes FindDefaultCredentialsWithParams with the specified scopes.
159+ func FindDefaultCredentials (ctx context.Context , scopes ... string ) (* Credentials , error ) {
160+ var params CredentialsParams
161+ params .Scopes = scopes
162+ return FindDefaultCredentialsWithParams (ctx , params )
163+ }
164+
165+ // CredentialsFromJSONWithParams obtains Google credentials from a JSON value. The JSON can
166+ // represent either a Google Developers Console client_credentials.json file (as in ConfigFromJSON),
167+ // a Google Developers service account key file, a gcloud user credentials file (a.k.a. refresh
168+ // token JSON), or the JSON configuration file for workload identity federation in non-Google cloud
169+ // platforms (see https://cloud.google.com/iam/docs/how-to#using-workload-identity-federation).
170+ func CredentialsFromJSONWithParams (ctx context.Context , jsonData []byte , params CredentialsParams ) (* Credentials , error ) {
171+ // Make defensive copy of the slices in params.
172+ params = params .deepCopy ()
173+
174+ // First, attempt to parse jsonData as a Google Developers Console client_credentials.json.
175+ config , _ := ConfigFromJSON (jsonData , params .Scopes ... )
176+ if config != nil {
177+ return & Credentials {
178+ ProjectID : "" ,
179+ TokenSource : authhandler .TokenSource (ctx , config , params .State , params .AuthHandler ),
180+ JSON : jsonData ,
181+ }, nil
182+ }
183+
184+ // Otherwise, parse jsonData as one of the other supported credentials files.
135185 var f credentialsFile
136186 if err := json .Unmarshal (jsonData , & f ); err != nil {
137187 return nil , err
138188 }
139- ts , err := f .tokenSource (ctx , append ([] string ( nil ), scopes ... ) )
189+ ts , err := f .tokenSource (ctx , params )
140190 if err != nil {
141191 return nil , err
142192 }
@@ -147,6 +197,13 @@ func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string)
147197 }, nil
148198}
149199
200+ // CredentialsFromJSON invokes CredentialsFromJSONWithParams with the specified scopes.
201+ func CredentialsFromJSON (ctx context.Context , jsonData []byte , scopes ... string ) (* Credentials , error ) {
202+ var params CredentialsParams
203+ params .Scopes = scopes
204+ return CredentialsFromJSONWithParams (ctx , jsonData , params )
205+ }
206+
150207func wellKnownFile () string {
151208 const f = "application_default_credentials.json"
152209 if runtime .GOOS == "windows" {
@@ -155,10 +212,10 @@ func wellKnownFile() string {
155212 return filepath .Join (guessUnixHomeDir (), ".config" , "gcloud" , f )
156213}
157214
158- func readCredentialsFile (ctx context.Context , filename string , scopes [] string ) (* DefaultCredentials , error ) {
215+ func readCredentialsFile (ctx context.Context , filename string , params CredentialsParams ) (* DefaultCredentials , error ) {
159216 b , err := ioutil .ReadFile (filename )
160217 if err != nil {
161218 return nil , err
162219 }
163- return CredentialsFromJSON (ctx , b , scopes ... )
220+ return CredentialsFromJSONWithParams (ctx , b , params )
164221}
0 commit comments