diff --git a/google/internal/externalaccount/sts_exchange.go b/google/internal/externalaccount/sts_exchange.go index 7571a0b..fb90be3 100644 --- a/google/internal/externalaccount/sts_exchange.go +++ b/google/internal/externalaccount/sts_exchange.go @@ -16,6 +16,10 @@ import ( "strings" ) +// ExchangeToken preforms a oauth2 token exchange with the provided endpoint. +// The first 4 fields are all mandatory. headers can be used to pass additional +// headers beyond the bare minimum required by the token exchange. options can +// be used to pass additional JSON-structured options to the remote server. func ExchangeToken(ctx context.Context, endpoint string, request *STSTokenExchangeRequest, authentication ClientAuthentication, headers http.Header, options map[string]interface{}) (*STSTokenExchangeResponse, error) { client := oauth2.NewClient(ctx, nil) @@ -63,9 +67,11 @@ func ExchangeToken(ctx context.Context, endpoint string, request *STSTokenExchan } + return &stsResp, nil } +// STSTokenExchangeRequest contains fields necessary to make an oauth2 token exchange. type STSTokenExchangeRequest struct { ActingParty struct { ActorToken string @@ -80,6 +86,7 @@ type STSTokenExchangeRequest struct { SubjectTokenType string } +// STSTokenExchangeResponse is used to decode the remote server's response during an oauth2 token exchange. type STSTokenExchangeResponse struct { AccessToken string `json:"access_token"` IssuedTokenType string `json:"issued_token_type"` diff --git a/google/internal/externalaccount/sts_exchange_test.go b/google/internal/externalaccount/sts_exchange_test.go index 1846b02..e8bc0d0 100644 --- a/google/internal/externalaccount/sts_exchange_test.go +++ b/google/internal/externalaccount/sts_exchange_test.go @@ -47,7 +47,6 @@ var expectedToken = STSTokenExchangeResponse{ } func TestExchangeToken(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { t.Errorf("Unexpected request method, %v is found", r.Method) @@ -55,24 +54,23 @@ func TestExchangeToken(t *testing.T) { if r.URL.String() != "/" { t.Errorf("Unexpected request URL, %v is found", r.URL) } - headerAuth := r.Header.Get("Authorization") - if headerAuth != "Basic cmJyZ25vZ25yaG9uZ28zYmk0Z2I5Z2hnOWc6bm90c29zZWNyZXQ=" { - t.Errorf("Unexpected autohrization header, %v is found", headerAuth) + if got, want := r.Header.Get("Authorization"), "Basic cmJyZ25vZ25yaG9uZ28zYmk0Z2I5Z2hnOWc6bm90c29zZWNyZXQ="; got != want { + t.Errorf("Unexpected authorization header, got %v, want %v", got, want) } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found", headerContentType) + if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want{ + t.Errorf("Unexpected Content-Type header, got %v, want %v", got, want) } body, err := ioutil.ReadAll(r.Body) if err != nil { t.Errorf("Failed reading request body: %v.", err) } - if string(body) != requestbody { - t.Errorf("Unexpected exchange payload, %v is found", string(body)) + if got, want := string(body), requestbody; got != want { + t.Errorf("Unexpected exchange payload, got %v but want %v", got, want) } w.Header().Set("Content-Type", "application/json") w.Write([]byte(responseBody)) })) + defer ts.Close() headers := http.Header{} headers.Add("Content-Type", "application/x-www-form-urlencoded") @@ -95,6 +93,7 @@ func TestExchangeToken_Err(t *testing.T) { w.Header().Set("Content-Type", "application/json") w.Write([]byte("what's wrong with this response?")) })) + defer ts.Close() headers := http.Header{} headers.Add("Content-Type", "application/x-www-form-urlencoded") @@ -113,7 +112,7 @@ func TestExchangeToken_Opts(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - t.Errorf("Failed reading request body: %v.", err) + t.Fatalf("Failed reading request body: %v.", err) } data, err := url.ParseQuery(string(body)) if err != nil { @@ -128,7 +127,7 @@ func TestExchangeToken_Opts(t *testing.T) { var opts map[string]interface{} err = json.Unmarshal([]byte(strOpts[0]), &opts) if len(opts) < 2 { - t.Errorf("Too few options recieved.") + t.Errorf("Too few options received.") } val, ok := opts["one"] @@ -139,11 +138,11 @@ func TestExchangeToken_Opts(t *testing.T) { if !ok { t.Errorf("Failed to assert the first option parameter as type testOpts.") } else { - if tOpts1["first"].(string) != optsValues[0][0] { - t.Errorf("First value in first options field is incorrect; want %v but got %v", tOpts1["first"].(string), optsValues[0][0]) + if got, want := tOpts1["first"].(string), optsValues[0][0]; got != want { + t.Errorf("First value in first options field is incorrect; got %v but want %v", got, want) } - if tOpts1["second"].(string) != optsValues[0][1] { - t.Errorf("Second value in first options field is incorrect; want %v but got %v", tOpts1["second"].(string), optsValues[0][1]) + if got, want := tOpts1["second"].(string), optsValues[0][1]; got != want { + t.Errorf("Second value in first options field is incorrect; got %v but want %v", got, want) } } } @@ -156,11 +155,11 @@ func TestExchangeToken_Opts(t *testing.T) { if !ok { t.Errorf("Failed to assert the second option parameter as type testOpts.") } else { - if tOpts2["first"].(string) != optsValues[1][0] { - t.Errorf("First value in second options field is incorrect; want %v but got %v", tOpts2["first"].(string), optsValues[1][0]) + if got, want := tOpts2["first"].(string), optsValues[1][0]; got != want { + t.Errorf("First value in second options field is incorrect; got %v but want %v", got, want) } - if tOpts2["second"].(string) != optsValues[1][1] { - t.Errorf("Second value in second options field is incorrect; want %v but got %v", tOpts2["second"].(string), optsValues[1][1]) + if got, want := tOpts2["second"].(string), optsValues[1][1]; got != want { + t.Errorf("Second value in second options field is incorrect; got %v but want %v", got, want) } } } @@ -170,6 +169,7 @@ func TestExchangeToken_Opts(t *testing.T) { w.Write([]byte(responseBody)) })) + defer ts.Close() headers := http.Header{} headers.Add("Content-Type", "application/x-www-form-urlencoded")