blob: 078e75ec78bfd6a3b81973577ba25e7b7fef2977 [file] [log] [blame]
Andrew Gerrand038cb4a2015-08-27 10:42:02 +10001// Copyright 2014 The Go Authors. All rights reserved.
Aaron Torresa8c019d2015-01-16 14:43:33 -08002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package clientcredentials
6
7import (
Jaana Burcu Doganc10ba272016-08-24 15:40:36 -07008 "context"
Brad Fitzpatrick80673b42019-01-14 22:52:49 +00009 "io"
Aaron Torresa8c019d2015-01-16 14:43:33 -080010 "io/ioutil"
11 "net/http"
12 "net/http/httptest"
Richard Musiol01b79d92017-02-10 14:32:30 -080013 "net/url"
Aaron Torresa8c019d2015-01-16 14:43:33 -080014 "testing"
Aaron Torresa8c019d2015-01-16 14:43:33 -080015)
16
Richard Musiol01b79d92017-02-10 14:32:30 -080017func newConf(serverURL string) *Config {
Aaron Torresa8c019d2015-01-16 14:43:33 -080018 return &Config{
Richard Musiol01b79d92017-02-10 14:32:30 -080019 ClientID: "CLIENT_ID",
20 ClientSecret: "CLIENT_SECRET",
21 Scopes: []string{"scope1", "scope2"},
22 TokenURL: serverURL + "/token",
23 EndpointParams: url.Values{"audience": {"audience1"}},
Aaron Torresa8c019d2015-01-16 14:43:33 -080024 }
25}
26
27type mockTransport struct {
28 rt func(req *http.Request) (resp *http.Response, err error)
29}
30
31func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
32 return t.rt(req)
33}
34
Tom Payne99b60b72019-01-29 22:49:30 +000035func TestTokenSourceGrantTypeOverride(t *testing.T) {
36 wantGrantType := "password"
37 var gotGrantType string
38 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
39 body, err := ioutil.ReadAll(r.Body)
40 if err != nil {
41 t.Errorf("ioutil.ReadAll(r.Body) == %v, %v, want _, <nil>", body, err)
42 }
43 if err := r.Body.Close(); err != nil {
44 t.Errorf("r.Body.Close() == %v, want <nil>", err)
45 }
46 values, err := url.ParseQuery(string(body))
47 if err != nil {
48 t.Errorf("url.ParseQuery(%q) == %v, %v, want _, <nil>", body, values, err)
49 }
50 gotGrantType = values.Get("grant_type")
51 w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
52 w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&token_type=bearer"))
53 }))
54 config := &Config{
55 ClientID: "CLIENT_ID",
56 ClientSecret: "CLIENT_SECRET",
57 Scopes: []string{"scope"},
58 TokenURL: ts.URL + "/token",
59 EndpointParams: url.Values{
60 "grant_type": {wantGrantType},
61 },
62 }
63 token, err := config.TokenSource(context.Background()).Token()
64 if err != nil {
65 t.Errorf("config.TokenSource(_).Token() == %v, %v, want !<nil>, <nil>", token, err)
66 }
67 if gotGrantType != wantGrantType {
68 t.Errorf("grant_type == %q, want %q", gotGrantType, wantGrantType)
69 }
70}
71
Aaron Torresa8c019d2015-01-16 14:43:33 -080072func TestTokenRequest(t *testing.T) {
73 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
74 if r.URL.String() != "/token" {
75 t.Errorf("authenticate client request URL = %q; want %q", r.URL, "/token")
76 }
77 headerAuth := r.Header.Get("Authorization")
78 if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" {
79 t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
80 }
81 if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want {
82 t.Errorf("Content-Type header = %q; want %q", got, want)
83 }
84 body, err := ioutil.ReadAll(r.Body)
85 if err != nil {
86 r.Body.Close()
87 }
88 if err != nil {
89 t.Errorf("failed reading request body: %s.", err)
90 }
Richard Musiol01b79d92017-02-10 14:32:30 -080091 if string(body) != "audience=audience1&grant_type=client_credentials&scope=scope1+scope2" {
Pablo Lalloni4464e782016-06-04 01:11:54 -030092 t.Errorf("payload = %q; want %q", string(body), "grant_type=client_credentials&scope=scope1+scope2")
Aaron Torresa8c019d2015-01-16 14:43:33 -080093 }
94 w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
95 w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&token_type=bearer"))
96 }))
97 defer ts.Close()
98 conf := newConf(ts.URL)
Jaana Burcu Doganc10ba272016-08-24 15:40:36 -070099 tok, err := conf.Token(context.Background())
Aaron Torresa8c019d2015-01-16 14:43:33 -0800100 if err != nil {
101 t.Error(err)
102 }
103 if !tok.Valid() {
104 t.Fatalf("token invalid. got: %#v", tok)
105 }
106 if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" {
107 t.Errorf("Access token = %q; want %q", tok.AccessToken, "90d64460d14870c08c81352a05dedd3465940a7c")
108 }
109 if tok.TokenType != "bearer" {
110 t.Errorf("token type = %q; want %q", tok.TokenType, "bearer")
111 }
112}
113
114func TestTokenRefreshRequest(t *testing.T) {
115 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
116 if r.URL.String() == "/somethingelse" {
117 return
118 }
119 if r.URL.String() != "/token" {
Brad Fitzpatrick80673b42019-01-14 22:52:49 +0000120 t.Errorf("Unexpected token refresh request URL: %q", r.URL)
Aaron Torresa8c019d2015-01-16 14:43:33 -0800121 }
122 headerContentType := r.Header.Get("Content-Type")
Brad Fitzpatrick80673b42019-01-14 22:52:49 +0000123 if got, want := headerContentType, "application/x-www-form-urlencoded"; got != want {
124 t.Errorf("Content-Type = %q; want %q", got, want)
Aaron Torresa8c019d2015-01-16 14:43:33 -0800125 }
126 body, _ := ioutil.ReadAll(r.Body)
Brad Fitzpatrick80673b42019-01-14 22:52:49 +0000127 const want = "audience=audience1&grant_type=client_credentials&scope=scope1+scope2"
128 if string(body) != want {
129 t.Errorf("Unexpected refresh token payload.\n got: %s\nwant: %s\n", body, want)
Aaron Torresa8c019d2015-01-16 14:43:33 -0800130 }
Brad Fitzpatrick80673b42019-01-14 22:52:49 +0000131 w.Header().Set("Content-Type", "application/json")
132 io.WriteString(w, `{"access_token": "foo", "refresh_token": "bar"}`)
Aaron Torresa8c019d2015-01-16 14:43:33 -0800133 }))
134 defer ts.Close()
135 conf := newConf(ts.URL)
Jaana Burcu Doganc10ba272016-08-24 15:40:36 -0700136 c := conf.Client(context.Background())
Aaron Torresa8c019d2015-01-16 14:43:33 -0800137 c.Get(ts.URL + "/somethingelse")
138}