1
2
3
4
5 package oauth2
6
7 import (
8 "context"
9 "errors"
10 "fmt"
11 "io"
12 "io/ioutil"
13 "net/http"
14 "net/http/httptest"
15 "net/url"
16 "testing"
17 "time"
18 )
19
20 type mockTransport struct {
21 rt func(req *http.Request) (resp *http.Response, err error)
22 }
23
24 func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
25 return t.rt(req)
26 }
27
28 func newConf(url string) *Config {
29 return &Config{
30 ClientID: "CLIENT_ID",
31 ClientSecret: "CLIENT_SECRET",
32 RedirectURL: "REDIRECT_URL",
33 Scopes: []string{"scope1", "scope2"},
34 Endpoint: Endpoint{
35 AuthURL: url + "/auth",
36 TokenURL: url + "/token",
37 },
38 }
39 }
40
41 func TestAuthCodeURL(t *testing.T) {
42 conf := newConf("server")
43 url := conf.AuthCodeURL("foo", AccessTypeOffline, ApprovalForce)
44 const want = "server/auth?access_type=offline&client_id=CLIENT_ID&prompt=consent&redirect_uri=REDIRECT_URL&response_type=code&scope=scope1+scope2&state=foo"
45 if got := url; got != want {
46 t.Errorf("got auth code URL = %q; want %q", got, want)
47 }
48 }
49
50 func TestAuthCodeURL_CustomParam(t *testing.T) {
51 conf := newConf("server")
52 param := SetAuthURLParam("foo", "bar")
53 url := conf.AuthCodeURL("baz", param)
54 const want = "server/auth?client_id=CLIENT_ID&foo=bar&redirect_uri=REDIRECT_URL&response_type=code&scope=scope1+scope2&state=baz"
55 if got := url; got != want {
56 t.Errorf("got auth code = %q; want %q", got, want)
57 }
58 }
59
60 func TestAuthCodeURL_Optional(t *testing.T) {
61 conf := &Config{
62 ClientID: "CLIENT_ID",
63 Endpoint: Endpoint{
64 AuthURL: "/auth-url",
65 TokenURL: "/token-url",
66 },
67 }
68 url := conf.AuthCodeURL("")
69 const want = "/auth-url?client_id=CLIENT_ID&response_type=code"
70 if got := url; got != want {
71 t.Fatalf("got auth code = %q; want %q", got, want)
72 }
73 }
74
75 func TestURLUnsafeClientConfig(t *testing.T) {
76 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
77 if got, want := r.Header.Get("Authorization"), "Basic Q0xJRU5UX0lEJTNGJTNGOkNMSUVOVF9TRUNSRVQlM0YlM0Y="; got != want {
78 t.Errorf("Authorization header = %q; want %q", got, want)
79 }
80
81 w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
82 w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer"))
83 }))
84 defer ts.Close()
85 conf := newConf(ts.URL)
86 conf.ClientID = "CLIENT_ID??"
87 conf.ClientSecret = "CLIENT_SECRET??"
88 _, err := conf.Exchange(context.Background(), "exchange-code")
89 if err != nil {
90 t.Error(err)
91 }
92 }
93
94 func TestExchangeRequest(t *testing.T) {
95 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
96 if r.URL.String() != "/token" {
97 t.Errorf("Unexpected exchange request URL %q", r.URL)
98 }
99 headerAuth := r.Header.Get("Authorization")
100 if want := "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ="; headerAuth != want {
101 t.Errorf("Unexpected authorization header %q, want %q", headerAuth, want)
102 }
103 headerContentType := r.Header.Get("Content-Type")
104 if headerContentType != "application/x-www-form-urlencoded" {
105 t.Errorf("Unexpected Content-Type header %q", headerContentType)
106 }
107 body, err := ioutil.ReadAll(r.Body)
108 if err != nil {
109 t.Errorf("Failed reading request body: %s.", err)
110 }
111 if string(body) != "code=exchange-code&grant_type=authorization_code&redirect_uri=REDIRECT_URL" {
112 t.Errorf("Unexpected exchange payload; got %q", body)
113 }
114 w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
115 w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer"))
116 }))
117 defer ts.Close()
118 conf := newConf(ts.URL)
119 tok, err := conf.Exchange(context.Background(), "exchange-code")
120 if err != nil {
121 t.Error(err)
122 }
123 if !tok.Valid() {
124 t.Fatalf("Token invalid. Got: %#v", tok)
125 }
126 if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" {
127 t.Errorf("Unexpected access token, %#v.", tok.AccessToken)
128 }
129 if tok.TokenType != "bearer" {
130 t.Errorf("Unexpected token type, %#v.", tok.TokenType)
131 }
132 scope := tok.Extra("scope")
133 if scope != "user" {
134 t.Errorf("Unexpected value for scope: %v", scope)
135 }
136 }
137
138 func TestExchangeRequest_CustomParam(t *testing.T) {
139 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
140 if r.URL.String() != "/token" {
141 t.Errorf("Unexpected exchange request URL, %v is found.", r.URL)
142 }
143 headerAuth := r.Header.Get("Authorization")
144 if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" {
145 t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
146 }
147 headerContentType := r.Header.Get("Content-Type")
148 if headerContentType != "application/x-www-form-urlencoded" {
149 t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
150 }
151 body, err := ioutil.ReadAll(r.Body)
152 if err != nil {
153 t.Errorf("Failed reading request body: %s.", err)
154 }
155 if string(body) != "code=exchange-code&foo=bar&grant_type=authorization_code&redirect_uri=REDIRECT_URL" {
156 t.Errorf("Unexpected exchange payload, %v is found.", string(body))
157 }
158 w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
159 w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer"))
160 }))
161 defer ts.Close()
162 conf := newConf(ts.URL)
163
164 param := SetAuthURLParam("foo", "bar")
165 tok, err := conf.Exchange(context.Background(), "exchange-code", param)
166 if err != nil {
167 t.Error(err)
168 }
169 if !tok.Valid() {
170 t.Fatalf("Token invalid. Got: %#v", tok)
171 }
172 if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" {
173 t.Errorf("Unexpected access token, %#v.", tok.AccessToken)
174 }
175 if tok.TokenType != "bearer" {
176 t.Errorf("Unexpected token type, %#v.", tok.TokenType)
177 }
178 scope := tok.Extra("scope")
179 if scope != "user" {
180 t.Errorf("Unexpected value for scope: %v", scope)
181 }
182 }
183
184 func TestExchangeRequest_JSONResponse(t *testing.T) {
185 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
186 if r.URL.String() != "/token" {
187 t.Errorf("Unexpected exchange request URL, %v is found.", r.URL)
188 }
189 headerAuth := r.Header.Get("Authorization")
190 if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" {
191 t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
192 }
193 headerContentType := r.Header.Get("Content-Type")
194 if headerContentType != "application/x-www-form-urlencoded" {
195 t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
196 }
197 body, err := ioutil.ReadAll(r.Body)
198 if err != nil {
199 t.Errorf("Failed reading request body: %s.", err)
200 }
201 if string(body) != "code=exchange-code&grant_type=authorization_code&redirect_uri=REDIRECT_URL" {
202 t.Errorf("Unexpected exchange payload, %v is found.", string(body))
203 }
204 w.Header().Set("Content-Type", "application/json")
205 w.Write([]byte(`{"access_token": "90d64460d14870c08c81352a05dedd3465940a7c", "scope": "user", "token_type": "bearer", "expires_in": 86400}`))
206 }))
207 defer ts.Close()
208 conf := newConf(ts.URL)
209 tok, err := conf.Exchange(context.Background(), "exchange-code")
210 if err != nil {
211 t.Error(err)
212 }
213 if !tok.Valid() {
214 t.Fatalf("Token invalid. Got: %#v", tok)
215 }
216 if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" {
217 t.Errorf("Unexpected access token, %#v.", tok.AccessToken)
218 }
219 if tok.TokenType != "bearer" {
220 t.Errorf("Unexpected token type, %#v.", tok.TokenType)
221 }
222 scope := tok.Extra("scope")
223 if scope != "user" {
224 t.Errorf("Unexpected value for scope: %v", scope)
225 }
226 expiresIn := tok.Extra("expires_in")
227 if expiresIn != float64(86400) {
228 t.Errorf("Unexpected non-numeric value for expires_in: %v", expiresIn)
229 }
230 }
231
232 func TestExtraValueRetrieval(t *testing.T) {
233 values := url.Values{}
234 kvmap := map[string]string{
235 "scope": "user", "token_type": "bearer", "expires_in": "86400.92",
236 "server_time": "1443571905.5606415", "referer_ip": "10.0.0.1",
237 "etag": "\"afZYj912P4alikMz_P11982\"", "request_id": "86400",
238 "untrimmed": " untrimmed ",
239 }
240 for key, value := range kvmap {
241 values.Set(key, value)
242 }
243
244 tok := Token{raw: values}
245 scope := tok.Extra("scope")
246 if got, want := scope, "user"; got != want {
247 t.Errorf("got scope = %q; want %q", got, want)
248 }
249 serverTime := tok.Extra("server_time")
250 if got, want := serverTime, 1443571905.5606415; got != want {
251 t.Errorf("got server_time value = %v; want %v", got, want)
252 }
253 refererIP := tok.Extra("referer_ip")
254 if got, want := refererIP, "10.0.0.1"; got != want {
255 t.Errorf("got referer_ip value = %v, want %v", got, want)
256 }
257 expiresIn := tok.Extra("expires_in")
258 if got, want := expiresIn, 86400.92; got != want {
259 t.Errorf("got expires_in value = %v, want %v", got, want)
260 }
261 requestID := tok.Extra("request_id")
262 if got, want := requestID, int64(86400); got != want {
263 t.Errorf("got request_id value = %v, want %v", got, want)
264 }
265 untrimmed := tok.Extra("untrimmed")
266 if got, want := untrimmed, " untrimmed "; got != want {
267 t.Errorf("got untrimmed = %q; want %q", got, want)
268 }
269 }
270
271 const day = 24 * time.Hour
272
273 func TestExchangeRequest_JSONResponse_Expiry(t *testing.T) {
274 seconds := int32(day.Seconds())
275 for _, c := range []struct {
276 name string
277 expires string
278 want bool
279 nullExpires bool
280 }{
281 {"normal", fmt.Sprintf(`"expires_in": %d`, seconds), true, false},
282 {"paypal", fmt.Sprintf(`"expires_in": "%d"`, seconds), true, false},
283 {"issue_239", fmt.Sprintf(`"expires_in": null`), true, true},
284
285 {"wrong_type", `"expires_in": false`, false, false},
286 {"wrong_type2", `"expires_in": {}`, false, false},
287 {"wrong_value", `"expires_in": "zzz"`, false, false},
288 } {
289 t.Run(c.name, func(t *testing.T) {
290 testExchangeRequest_JSONResponse_expiry(t, c.expires, c.want, c.nullExpires)
291 })
292 }
293 }
294
295 func testExchangeRequest_JSONResponse_expiry(t *testing.T, exp string, want, nullExpires bool) {
296 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
297 w.Header().Set("Content-Type", "application/json")
298 w.Write([]byte(fmt.Sprintf(`{"access_token": "90d", "scope": "user", "token_type": "bearer", %s}`, exp)))
299 }))
300 defer ts.Close()
301 conf := newConf(ts.URL)
302 t1 := time.Now().Add(day)
303 tok, err := conf.Exchange(context.Background(), "exchange-code")
304 t2 := t1.Add(day)
305
306 if got := (err == nil); got != want {
307 if want {
308 t.Errorf("unexpected error: got %v", err)
309 } else {
310 t.Errorf("unexpected success")
311 }
312 }
313 if !want {
314 return
315 }
316 if !tok.Valid() {
317 t.Fatalf("Token invalid. Got: %#v", tok)
318 }
319 expiry := tok.Expiry
320
321 if nullExpires && expiry.IsZero() {
322 return
323 }
324 if expiry.Before(t1) || expiry.After(t2) {
325 t.Errorf("Unexpected value for Expiry: %v (should be between %v and %v)", expiry, t1, t2)
326 }
327 }
328
329 func TestExchangeRequest_BadResponse(t *testing.T) {
330 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
331 w.Header().Set("Content-Type", "application/json")
332 w.Write([]byte(`{"scope": "user", "token_type": "bearer"}`))
333 }))
334 defer ts.Close()
335 conf := newConf(ts.URL)
336 _, err := conf.Exchange(context.Background(), "code")
337 if err == nil {
338 t.Error("expected error from missing access_token")
339 }
340 }
341
342 func TestExchangeRequest_BadResponseType(t *testing.T) {
343 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
344 w.Header().Set("Content-Type", "application/json")
345 w.Write([]byte(`{"access_token":123, "scope": "user", "token_type": "bearer"}`))
346 }))
347 defer ts.Close()
348 conf := newConf(ts.URL)
349 _, err := conf.Exchange(context.Background(), "exchange-code")
350 if err == nil {
351 t.Error("expected error from non-string access_token")
352 }
353 }
354
355 func TestExchangeRequest_NonBasicAuth(t *testing.T) {
356 tr := &mockTransport{
357 rt: func(r *http.Request) (w *http.Response, err error) {
358 headerAuth := r.Header.Get("Authorization")
359 if headerAuth != "" {
360 t.Errorf("Unexpected authorization header %q", headerAuth)
361 }
362 return nil, errors.New("no response")
363 },
364 }
365 c := &http.Client{Transport: tr}
366 conf := &Config{
367 ClientID: "CLIENT_ID",
368 Endpoint: Endpoint{
369 AuthURL: "https://accounts.google.com/auth",
370 TokenURL: "https://accounts.google.com/token",
371 AuthStyle: AuthStyleInParams,
372 },
373 }
374
375 ctx := context.WithValue(context.Background(), HTTPClient, c)
376 conf.Exchange(ctx, "code")
377 }
378
379 func TestPasswordCredentialsTokenRequest(t *testing.T) {
380 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
381 defer r.Body.Close()
382 expected := "/token"
383 if r.URL.String() != expected {
384 t.Errorf("URL = %q; want %q", r.URL, expected)
385 }
386 headerAuth := r.Header.Get("Authorization")
387 expected = "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ="
388 if headerAuth != expected {
389 t.Errorf("Authorization header = %q; want %q", headerAuth, expected)
390 }
391 headerContentType := r.Header.Get("Content-Type")
392 expected = "application/x-www-form-urlencoded"
393 if headerContentType != expected {
394 t.Errorf("Content-Type header = %q; want %q", headerContentType, expected)
395 }
396 body, err := ioutil.ReadAll(r.Body)
397 if err != nil {
398 t.Errorf("Failed reading request body: %s.", err)
399 }
400 expected = "grant_type=password&password=password1&scope=scope1+scope2&username=user1"
401 if string(body) != expected {
402 t.Errorf("res.Body = %q; want %q", string(body), expected)
403 }
404 w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
405 w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer"))
406 }))
407 defer ts.Close()
408 conf := newConf(ts.URL)
409 tok, err := conf.PasswordCredentialsToken(context.Background(), "user1", "password1")
410 if err != nil {
411 t.Error(err)
412 }
413 if !tok.Valid() {
414 t.Fatalf("Token invalid. Got: %#v", tok)
415 }
416 expected := "90d64460d14870c08c81352a05dedd3465940a7c"
417 if tok.AccessToken != expected {
418 t.Errorf("AccessToken = %q; want %q", tok.AccessToken, expected)
419 }
420 expected = "bearer"
421 if tok.TokenType != expected {
422 t.Errorf("TokenType = %q; want %q", tok.TokenType, expected)
423 }
424 }
425
426 func TestTokenRefreshRequest(t *testing.T) {
427 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
428 if r.URL.String() == "/somethingelse" {
429 return
430 }
431 if r.URL.String() != "/token" {
432 t.Errorf("Unexpected token refresh request URL %q", r.URL)
433 }
434 headerContentType := r.Header.Get("Content-Type")
435 if headerContentType != "application/x-www-form-urlencoded" {
436 t.Errorf("Unexpected Content-Type header %q", headerContentType)
437 }
438 body, _ := ioutil.ReadAll(r.Body)
439 if string(body) != "grant_type=refresh_token&refresh_token=REFRESH_TOKEN" {
440 t.Errorf("Unexpected refresh token payload %q", body)
441 }
442 w.Header().Set("Content-Type", "application/json")
443 io.WriteString(w, `{"access_token": "foo", "refresh_token": "bar"}`)
444 }))
445 defer ts.Close()
446 conf := newConf(ts.URL)
447 c := conf.Client(context.Background(), &Token{RefreshToken: "REFRESH_TOKEN"})
448 c.Get(ts.URL + "/somethingelse")
449 }
450
451 func TestFetchWithNoRefreshToken(t *testing.T) {
452 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
453 if r.URL.String() == "/somethingelse" {
454 return
455 }
456 if r.URL.String() != "/token" {
457 t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL)
458 }
459 headerContentType := r.Header.Get("Content-Type")
460 if headerContentType != "application/x-www-form-urlencoded" {
461 t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
462 }
463 body, _ := ioutil.ReadAll(r.Body)
464 if string(body) != "client_id=CLIENT_ID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN" {
465 t.Errorf("Unexpected refresh token payload, %v is found.", string(body))
466 }
467 }))
468 defer ts.Close()
469 conf := newConf(ts.URL)
470 c := conf.Client(context.Background(), nil)
471 _, err := c.Get(ts.URL + "/somethingelse")
472 if err == nil {
473 t.Errorf("Fetch should return an error if no refresh token is set")
474 }
475 }
476
477 func TestTokenRetrieveError(t *testing.T) {
478 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
479 if r.URL.String() != "/token" {
480 t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL)
481 }
482 w.Header().Set("Content-type", "application/json")
483
484 w.WriteHeader(http.StatusBadRequest)
485 w.Write([]byte(`{"error": "invalid_grant"}`))
486 }))
487 defer ts.Close()
488 conf := newConf(ts.URL)
489 _, err := conf.Exchange(context.Background(), "exchange-code")
490 if err == nil {
491 t.Fatalf("got no error, expected one")
492 }
493 re, ok := err.(*RetrieveError)
494 if !ok {
495 t.Fatalf("got %T error, expected *RetrieveError; error was: %v", err, err)
496 }
497 expected := `oauth2: "invalid_grant"`
498 if errStr := err.Error(); errStr != expected {
499 t.Fatalf("got %#v, expected %#v", errStr, expected)
500 }
501 expected = "invalid_grant"
502 if re.ErrorCode != expected {
503 t.Fatalf("got %#v, expected %#v", re.ErrorCode, expected)
504 }
505 }
506
507
508 func TestTokenRetrieveError200(t *testing.T) {
509 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
510 if r.URL.String() != "/token" {
511 t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL)
512 }
513 w.Header().Set("Content-type", "application/json")
514 w.Write([]byte(`{"error": "invalid_grant"}`))
515 }))
516 defer ts.Close()
517 conf := newConf(ts.URL)
518 _, err := conf.Exchange(context.Background(), "exchange-code")
519 if err == nil {
520 t.Fatalf("got no error, expected one")
521 }
522 re, ok := err.(*RetrieveError)
523 if !ok {
524 t.Fatalf("got %T error, expected *RetrieveError; error was: %v", err, err)
525 }
526 expected := `oauth2: "invalid_grant"`
527 if errStr := err.Error(); errStr != expected {
528 t.Fatalf("got %#v, expected %#v", errStr, expected)
529 }
530 expected = "invalid_grant"
531 if re.ErrorCode != expected {
532 t.Fatalf("got %#v, expected %#v", re.ErrorCode, expected)
533 }
534 }
535
536 func TestRefreshToken_RefreshTokenReplacement(t *testing.T) {
537 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
538 w.Header().Set("Content-Type", "application/json")
539 w.Write([]byte(`{"access_token":"ACCESS_TOKEN", "scope": "user", "token_type": "bearer", "refresh_token": "NEW_REFRESH_TOKEN"}`))
540 return
541 }))
542 defer ts.Close()
543 conf := newConf(ts.URL)
544 tkr := conf.TokenSource(context.Background(), &Token{RefreshToken: "OLD_REFRESH_TOKEN"})
545 tk, err := tkr.Token()
546 if err != nil {
547 t.Errorf("got err = %v; want none", err)
548 return
549 }
550 if want := "NEW_REFRESH_TOKEN"; tk.RefreshToken != want {
551 t.Errorf("RefreshToken = %q; want %q", tk.RefreshToken, want)
552 }
553 }
554
555 func TestRefreshToken_RefreshTokenPreservation(t *testing.T) {
556 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
557 w.Header().Set("Content-Type", "application/json")
558 w.Write([]byte(`{"access_token":"ACCESS_TOKEN", "scope": "user", "token_type": "bearer"}`))
559 return
560 }))
561 defer ts.Close()
562 conf := newConf(ts.URL)
563 const oldRefreshToken = "OLD_REFRESH_TOKEN"
564 tkr := conf.TokenSource(context.Background(), &Token{RefreshToken: oldRefreshToken})
565 tk, err := tkr.Token()
566 if err != nil {
567 t.Fatalf("got err = %v; want none", err)
568 }
569 if tk.RefreshToken != oldRefreshToken {
570 t.Errorf("RefreshToken = %q; want %q", tk.RefreshToken, oldRefreshToken)
571 }
572 }
573
574 func TestConfigClientWithToken(t *testing.T) {
575 tok := &Token{
576 AccessToken: "abc123",
577 }
578 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
579 if got, want := r.Header.Get("Authorization"), fmt.Sprintf("Bearer %s", tok.AccessToken); got != want {
580 t.Errorf("Authorization header = %q; want %q", got, want)
581 }
582 return
583 }))
584 defer ts.Close()
585 conf := newConf(ts.URL)
586
587 c := conf.Client(context.Background(), tok)
588 req, err := http.NewRequest("GET", ts.URL, nil)
589 if err != nil {
590 t.Error(err)
591 }
592 _, err = c.Do(req)
593 if err != nil {
594 t.Error(err)
595 }
596 }
597
View as plain text