From 01b79d94479495d23e14e5ddc8f85a9271aff260 Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Fri, 10 Feb 2017 14:32:30 -0800 Subject: [PATCH] clientcredentials: add option for additional endpoint parameters This is to support https://auth0.com/docs/api-auth/config/asking-for-access-tokens. Fixes https://github.com/golang/oauth2/issues/216 Change-Id: I9b8fdb4fe22c688fd71e43bd21d80b796434b8b0 Reviewed-on: https://go-review.googlesource.com/36880 Run-TryBot: Ian Lance Taylor Reviewed-by: Jaana Burcu Dogan Reviewed-by: Brad Fitzpatrick --- clientcredentials/clientcredentials.go | 15 +++++++++++++-- clientcredentials/clientcredentials_test.go | 16 +++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/clientcredentials/clientcredentials.go b/clientcredentials/clientcredentials.go index 26bc838..29374af 100644 --- a/clientcredentials/clientcredentials.go +++ b/clientcredentials/clientcredentials.go @@ -14,6 +14,7 @@ package clientcredentials // import "golang.org/x/oauth2/clientcredentials" import ( + "fmt" "net/http" "net/url" "strings" @@ -38,6 +39,9 @@ type Config struct { // Scope specifies optional requested permissions. Scopes []string + + // EndpointParams specifies additional parameters for requests to the token endpoint. + EndpointParams url.Values } // Token uses client credentials to retrieve a token. @@ -76,10 +80,17 @@ type tokenSource struct { // Token refreshes the token by using a new client credentials request. // tokens received this way do not include a refresh token func (c *tokenSource) Token() (*oauth2.Token, error) { - tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, url.Values{ + v := url.Values{ "grant_type": {"client_credentials"}, "scope": internal.CondVal(strings.Join(c.conf.Scopes, " ")), - }) + } + for k, p := range c.conf.EndpointParams { + if _, ok := v[k]; ok { + return nil, fmt.Errorf("oauth2: cannot overwrite parameter %q", k) + } + v[k] = p + } + tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v) if err != nil { return nil, err } diff --git a/clientcredentials/clientcredentials_test.go b/clientcredentials/clientcredentials_test.go index a18e95a..108520c 100644 --- a/clientcredentials/clientcredentials_test.go +++ b/clientcredentials/clientcredentials_test.go @@ -9,15 +9,17 @@ import ( "io/ioutil" "net/http" "net/http/httptest" + "net/url" "testing" ) -func newConf(url string) *Config { +func newConf(serverURL string) *Config { return &Config{ - ClientID: "CLIENT_ID", - ClientSecret: "CLIENT_SECRET", - Scopes: []string{"scope1", "scope2"}, - TokenURL: url + "/token", + ClientID: "CLIENT_ID", + ClientSecret: "CLIENT_SECRET", + Scopes: []string{"scope1", "scope2"}, + TokenURL: serverURL + "/token", + EndpointParams: url.Values{"audience": {"audience1"}}, } } @@ -48,7 +50,7 @@ func TestTokenRequest(t *testing.T) { if err != nil { t.Errorf("failed reading request body: %s.", err) } - if string(body) != "grant_type=client_credentials&scope=scope1+scope2" { + if string(body) != "audience=audience1&grant_type=client_credentials&scope=scope1+scope2" { t.Errorf("payload = %q; want %q", string(body), "grant_type=client_credentials&scope=scope1+scope2") } w.Header().Set("Content-Type", "application/x-www-form-urlencoded") @@ -84,7 +86,7 @@ func TestTokenRefreshRequest(t *testing.T) { t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) } body, _ := ioutil.ReadAll(r.Body) - if string(body) != "grant_type=client_credentials&scope=scope1+scope2" { + if string(body) != "audience=audience1&grant_type=client_credentials&scope=scope1+scope2" { t.Errorf("Unexpected refresh token payload, %v is found.", string(body)) } }))