1
2
3
4
5 package clientcredentials
6
7 import (
8 "context"
9 "io"
10 "io/ioutil"
11 "net/http"
12 "net/http/httptest"
13 "net/url"
14 "testing"
15 )
16
17 func newConf(serverURL string) *Config {
18 return &Config{
19 ClientID: "CLIENT_ID",
20 ClientSecret: "CLIENT_SECRET",
21 Scopes: []string{"scope1", "scope2"},
22 TokenURL: serverURL + "/token",
23 EndpointParams: url.Values{"audience": {"audience1"}},
24 }
25 }
26
27 type mockTransport struct {
28 rt func(req *http.Request) (resp *http.Response, err error)
29 }
30
31 func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
32 return t.rt(req)
33 }
34
35 func 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
72 func 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 }
91 if string(body) != "audience=audience1&grant_type=client_credentials&scope=scope1+scope2" {
92 t.Errorf("payload = %q; want %q", string(body), "grant_type=client_credentials&scope=scope1+scope2")
93 }
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)
99 tok, err := conf.Token(context.Background())
100 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
114 func 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" {
120 t.Errorf("Unexpected token refresh request URL: %q", r.URL)
121 }
122 headerContentType := r.Header.Get("Content-Type")
123 if got, want := headerContentType, "application/x-www-form-urlencoded"; got != want {
124 t.Errorf("Content-Type = %q; want %q", got, want)
125 }
126 body, _ := ioutil.ReadAll(r.Body)
127 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)
130 }
131 w.Header().Set("Content-Type", "application/json")
132 io.WriteString(w, `{"access_token": "foo", "refresh_token": "bar"}`)
133 }))
134 defer ts.Close()
135 conf := newConf(ts.URL)
136 c := conf.Client(context.Background())
137 c.Get(ts.URL + "/somethingelse")
138 }
139
View as plain text