@@ -359,6 +359,90 @@ func TestDefaultCredentials_ClientCredentials(t *testing.T) {
359359 }
360360}
361361
362+ // Better coverage of all external account features tested in the sub-package.
363+ func TestDefaultCredentials_ExternalAccountKey (t * testing.T ) {
364+ b , err := os .ReadFile ("../internal/testdata/exaccount_url.json" )
365+ if err != nil {
366+ t .Fatal (err )
367+ }
368+ f , err := internaldetect .ParseExternalAccount (b )
369+ if err != nil {
370+ t .Fatal (err )
371+ }
372+ ts := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
373+ defer r .Body .Close ()
374+ if r .URL .Path == "/token" {
375+ resp := & struct {
376+ Token string `json:"id_token"`
377+ }{
378+ Token : "a_fake_token_base" ,
379+ }
380+ if err := json .NewEncoder (w ).Encode (& resp ); err != nil {
381+ t .Error (err )
382+ }
383+ } else if r .URL .Path == "/sts" {
384+ r .ParseForm ()
385+ if got , want := r .Form .Get ("subject_token" ), "a_fake_token_base" ; got != want {
386+ t .Errorf ("got %q, want %q" , got , want )
387+ }
388+
389+ resp := & struct {
390+ AccessToken string `json:"access_token"`
391+ ExpiresIn int `json:"expires_in"`
392+ }{
393+ AccessToken : "a_fake_token_sts" ,
394+ ExpiresIn : 60 ,
395+ }
396+ if err := json .NewEncoder (w ).Encode (& resp ); err != nil {
397+ t .Error (err )
398+ }
399+ } else if r .URL .Path == "/impersonate" {
400+ if want := "a_fake_token_sts" ; ! strings .Contains (r .Header .Get ("Authorization" ), want ) {
401+ t .Errorf ("missing sts token: got %q, want %q" , r .Header .Get ("Authorization" ), want )
402+ }
403+
404+ resp := & struct {
405+ AccessToken string `json:"accessToken"`
406+ ExpireTime string `json:"expireTime"`
407+ }{
408+ AccessToken : "a_fake_token" ,
409+ ExpireTime : "2006-01-02T15:04:05Z" ,
410+ }
411+ if err := json .NewEncoder (w ).Encode (& resp ); err != nil {
412+ t .Error (err )
413+ }
414+ } else {
415+ t .Errorf ("unexpected call to %q" , r .URL .Path )
416+ }
417+ }))
418+ f .ServiceAccountImpersonationURL = ts .URL + "/impersonate"
419+ f .CredentialSource .URL = ts .URL + "/token"
420+ f .TokenURL = ts .URL + "/sts"
421+ b , err = json .Marshal (f )
422+ if err != nil {
423+ t .Fatal (err )
424+ }
425+
426+ creds , err := DefaultCredentials (& Options {
427+ CredentialsJSON : b ,
428+ Scopes : []string {"https://www.googleapis.com/auth/cloud-platform" },
429+ UseSelfSignedJWT : true ,
430+ })
431+ if err != nil {
432+ t .Fatal (err )
433+ }
434+ tok , err := creds .Token (context .Background ())
435+ if err != nil {
436+ t .Fatalf ("creds.Token() = %v" , err )
437+ }
438+ if want := "a_fake_token" ; tok .Value != want {
439+ t .Fatalf ("got %q, want %q" , tok .Value , want )
440+ }
441+ if want := internal .TokenTypeBearer ; tok .Type != want {
442+ t .Fatalf ("got %q, want %q" , tok .Type , want )
443+ }
444+ }
445+
362446func TestDefaultCredentials_Fails (t * testing.T ) {
363447 t .Setenv ("GOOGLE_APPLICATION_CREDENTIALS" , "nothingToSeeHere" )
364448 t .Setenv ("HOME" , "nothingToSeeHere" )
0 commit comments