Skip to content

Commit 99b60b7

Browse files
twpaynebradfitz
authored andcommitted
clientcredentials: allow override of grant_type
Password-based authentication to the [Keycloak](https://www.keycloak.org/) API requires `grant_type` to be `password`. It would be very helpful if `golang.org/x/oauth2` could be used for this, and all's that missing is the ability to override `grant_type`. Fixes #283 Change-Id: I439dccb3e57042571ad92f115442ae1b7d59d4e0 GitHub-Last-Rev: 0e6f85e GitHub-Pull-Request: #363 Reviewed-on: https://go-review.googlesource.com/c/158517 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 5dab416 commit 99b60b7

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

clientcredentials/clientcredentials.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ func (c *tokenSource) Token() (*oauth2.Token, error) {
9090
v.Set("scope", strings.Join(c.conf.Scopes, " "))
9191
}
9292
for k, p := range c.conf.EndpointParams {
93-
if _, ok := v[k]; ok {
93+
// Allow grant_type to be overridden to allow interoperability with
94+
// non-compliant implementations.
95+
if _, ok := v[k]; ok && k != "grant_type" {
9496
return nil, fmt.Errorf("oauth2: cannot overwrite parameter %q", k)
9597
}
9698
v[k] = p

clientcredentials/clientcredentials_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,43 @@ func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err e
3131
return t.rt(req)
3232
}
3333

34+
func TestTokenSourceGrantTypeOverride(t *testing.T) {
35+
wantGrantType := "password"
36+
var gotGrantType string
37+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
38+
body, err := ioutil.ReadAll(r.Body)
39+
if err != nil {
40+
t.Errorf("ioutil.ReadAll(r.Body) == %v, %v, want _, <nil>", body, err)
41+
}
42+
if err := r.Body.Close(); err != nil {
43+
t.Errorf("r.Body.Close() == %v, want <nil>", err)
44+
}
45+
values, err := url.ParseQuery(string(body))
46+
if err != nil {
47+
t.Errorf("url.ParseQuery(%q) == %v, %v, want _, <nil>", body, values, err)
48+
}
49+
gotGrantType = values.Get("grant_type")
50+
w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
51+
w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&token_type=bearer"))
52+
}))
53+
config := &Config{
54+
ClientID: "CLIENT_ID",
55+
ClientSecret: "CLIENT_SECRET",
56+
Scopes: []string{"scope"},
57+
TokenURL: ts.URL + "/token",
58+
EndpointParams: url.Values{
59+
"grant_type": {wantGrantType},
60+
},
61+
}
62+
token, err := config.TokenSource(context.Background()).Token()
63+
if err != nil {
64+
t.Errorf("config.TokenSource(_).Token() == %v, %v, want !<nil>, <nil>", token, err)
65+
}
66+
if gotGrantType != wantGrantType {
67+
t.Errorf("grant_type == %q, want %q", gotGrantType, wantGrantType)
68+
}
69+
}
70+
3471
func TestTokenRequest(t *testing.T) {
3572
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
3673
if r.URL.String() != "/token" {

0 commit comments

Comments
 (0)