Skip to content

Commit 83feb76

Browse files
committed
Sync with 'upstream/master'
2 parents 23290a8 + 9780585 commit 83feb76

35 files changed

+4035
-64
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# OAuth2 for Go
22

3+
[![Go Reference](https://pkg.go.dev/badge/golang.org/x/oauth2.svg)](https://pkg.go.dev/golang.org/x/oauth2)
34
[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2)
4-
[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2)
55

66
oauth2 package contains a client implementation for OAuth 2.0 spec.
77

@@ -14,17 +14,17 @@ go get golang.org/x/oauth2
1414
Or you can manually git clone the repository to
1515
`$(go env GOPATH)/src/golang.org/x/oauth2`.
1616

17-
See godoc for further documentation and examples.
17+
See pkg.go.dev for further documentation and examples.
1818

19-
* [godoc.org/golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2)
20-
* [godoc.org/golang.org/x/oauth2/google](https://godoc.org/golang.org/x/oauth2/google)
19+
* [pkg.go.dev/golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2)
20+
* [pkg.go.dev/golang.org/x/oauth2/google](https://pkg.go.dev/golang.org/x/oauth2/google)
2121

2222
## Policy for new packages
2323

2424
We no longer accept new provider-specific packages in this repo if all
2525
they do is add a single endpoint variable. If you just want to add a
2626
single endpoint, add it to the
27-
[godoc.org/golang.org/x/oauth2/endpoints](https://godoc.org/golang.org/x/oauth2/endpoints)
27+
[pkg.go.dev/golang.org/x/oauth2/endpoints](https://pkg.go.dev/golang.org/x/oauth2/endpoints)
2828
package.
2929

3030
## Report Issues / Send Patches

authhandler/authhandler.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package authhandler implements a TokenSource to support
6+
// "three-legged OAuth 2.0" via a custom AuthorizationHandler.
7+
package authhandler
8+
9+
import (
10+
"context"
11+
"errors"
12+
13+
"golang.org/x/oauth2"
14+
)
15+
16+
// AuthorizationHandler is a 3-legged-OAuth helper that prompts
17+
// the user for OAuth consent at the specified auth code URL
18+
// and returns an auth code and state upon approval.
19+
type AuthorizationHandler func(authCodeURL string) (code string, state string, err error)
20+
21+
// TokenSource returns an oauth2.TokenSource that fetches access tokens
22+
// using 3-legged-OAuth flow.
23+
//
24+
// The provided context.Context is used for oauth2 Exchange operation.
25+
//
26+
// The provided oauth2.Config should be a full configuration containing AuthURL,
27+
// TokenURL, and Scope.
28+
//
29+
// An environment-specific AuthorizationHandler is used to obtain user consent.
30+
//
31+
// Per the OAuth protocol, a unique "state" string should be specified here.
32+
// This token source will verify that the "state" is identical in the request
33+
// and response before exchanging the auth code for OAuth token to prevent CSRF
34+
// attacks.
35+
func TokenSource(ctx context.Context, config *oauth2.Config, state string, authHandler AuthorizationHandler) oauth2.TokenSource {
36+
return oauth2.ReuseTokenSource(nil, authHandlerSource{config: config, ctx: ctx, authHandler: authHandler, state: state})
37+
}
38+
39+
type authHandlerSource struct {
40+
ctx context.Context
41+
config *oauth2.Config
42+
authHandler AuthorizationHandler
43+
state string
44+
}
45+
46+
func (source authHandlerSource) Token() (*oauth2.Token, error) {
47+
url := source.config.AuthCodeURL(source.state)
48+
code, state, err := source.authHandler(url)
49+
if err != nil {
50+
return nil, err
51+
}
52+
if state != source.state {
53+
return nil, errors.New("state mismatch in 3-legged-OAuth flow")
54+
}
55+
return source.config.Exchange(source.ctx, code)
56+
}

authhandler/authhandler_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package authhandler
6+
7+
import (
8+
"context"
9+
"fmt"
10+
"net/http"
11+
"net/http/httptest"
12+
"testing"
13+
14+
"golang.org/x/oauth2"
15+
)
16+
17+
func TestTokenExchange_Success(t *testing.T) {
18+
authhandler := func(authCodeURL string) (string, string, error) {
19+
if authCodeURL == "testAuthCodeURL?client_id=testClientID&response_type=code&scope=pubsub&state=testState" {
20+
return "testCode", "testState", nil
21+
}
22+
return "", "", fmt.Errorf("invalid authCodeURL: %q", authCodeURL)
23+
}
24+
25+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
26+
r.ParseForm()
27+
if r.Form.Get("code") == "testCode" {
28+
w.Header().Set("Content-Type", "application/json")
29+
w.Write([]byte(`{
30+
"access_token": "90d64460d14870c08c81352a05dedd3465940a7c",
31+
"scope": "pubsub",
32+
"token_type": "bearer",
33+
"expires_in": 3600
34+
}`))
35+
}
36+
}))
37+
defer ts.Close()
38+
39+
conf := &oauth2.Config{
40+
ClientID: "testClientID",
41+
Scopes: []string{"pubsub"},
42+
Endpoint: oauth2.Endpoint{
43+
AuthURL: "testAuthCodeURL",
44+
TokenURL: ts.URL,
45+
},
46+
}
47+
48+
tok, err := TokenSource(context.Background(), conf, "testState", authhandler).Token()
49+
if err != nil {
50+
t.Fatal(err)
51+
}
52+
if !tok.Valid() {
53+
t.Errorf("got invalid token: %v", tok)
54+
}
55+
if got, want := tok.AccessToken, "90d64460d14870c08c81352a05dedd3465940a7c"; got != want {
56+
t.Errorf("access token = %q; want %q", got, want)
57+
}
58+
if got, want := tok.TokenType, "bearer"; got != want {
59+
t.Errorf("token type = %q; want %q", got, want)
60+
}
61+
if got := tok.Expiry.IsZero(); got {
62+
t.Errorf("token expiry is zero = %v, want false", got)
63+
}
64+
scope := tok.Extra("scope")
65+
if got, want := scope, "pubsub"; got != want {
66+
t.Errorf("scope = %q; want %q", got, want)
67+
}
68+
}
69+
70+
func TestTokenExchange_StateMismatch(t *testing.T) {
71+
authhandler := func(authCodeURL string) (string, string, error) {
72+
return "testCode", "testStateMismatch", nil
73+
}
74+
75+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
76+
w.Header().Set("Content-Type", "application/json")
77+
w.Write([]byte(`{
78+
"access_token": "90d64460d14870c08c81352a05dedd3465940a7c",
79+
"scope": "pubsub",
80+
"token_type": "bearer",
81+
"expires_in": 3600
82+
}`))
83+
}))
84+
defer ts.Close()
85+
86+
conf := &oauth2.Config{
87+
ClientID: "testClientID",
88+
Scopes: []string{"pubsub"},
89+
Endpoint: oauth2.Endpoint{
90+
AuthURL: "testAuthCodeURL",
91+
TokenURL: ts.URL,
92+
},
93+
}
94+
95+
_, err := TokenSource(context.Background(), conf, "testState", authhandler).Token()
96+
if want_err := "state mismatch in 3-legged-OAuth flow"; err == nil || err.Error() != want_err {
97+
t.Errorf("err = %q; want %q", err, want_err)
98+
}
99+
}

endpoints/endpoints.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ var Amazon = oauth2.Endpoint{
1717
TokenURL: "https://api.amazon.com/auth/o2/token",
1818
}
1919

20+
// Battlenet is the endpoint for Battlenet.
21+
var Battlenet = oauth2.Endpoint{
22+
AuthURL: "https://battle.net/oauth/authorize",
23+
TokenURL: "https://battle.net/oauth/token",
24+
}
25+
2026
// Bitbucket is the endpoint for Bitbucket.
2127
var Bitbucket = oauth2.Endpoint{
2228
AuthURL: "https://bitbucket.org/site/oauth2/authorize",
@@ -167,6 +173,12 @@ var StackOverflow = oauth2.Endpoint{
167173
TokenURL: "https://stackoverflow.com/oauth/access_token",
168174
}
169175

176+
// Strava is the endpoint for Strava.
177+
var Strava = oauth2.Endpoint{
178+
AuthURL: "https://www.strava.com/oauth/authorize",
179+
TokenURL: "https://www.strava.com/oauth/token",
180+
}
181+
170182
// Twitch is the endpoint for Twitch.
171183
var Twitch = oauth2.Endpoint{
172184
AuthURL: "https://id.twitch.tv/oauth2/authorize",
@@ -197,6 +209,12 @@ var Yandex = oauth2.Endpoint{
197209
TokenURL: "https://oauth.yandex.com/token",
198210
}
199211

212+
// Zoom is the endpoint for Zoom.
213+
var Zoom = oauth2.Endpoint{
214+
AuthURL: "https://zoom.us/oauth/authorize",
215+
TokenURL: "https://zoom.us/oauth/token",
216+
}
217+
200218
// AzureAD returns a new oauth2.Endpoint for the given tenant at Azure Active Directory.
201219
// If tenant is empty, it uses the tenant called `common`.
202220
//

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ go 1.11
44

55
require (
66
cloud.google.com/go v0.65.0
7-
golang.org/x/net v0.0.0-20200822124328-c89045814202
7+
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
88
google.golang.org/appengine v1.6.6
99
)

go.sum

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/
177177
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
178178
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
179179
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
180-
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
181180
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
181+
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
182+
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
182183
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
183184
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
184185
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -217,11 +218,15 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
217218
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
218219
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
219220
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
221+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
222+
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
223+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
220224
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
221225
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
222226
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
223227
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
224228
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
229+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
225230
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
226231
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
227232
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

google/appengine_gen1.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5+
//go:build appengine
56
// +build appengine
67

78
// This file applies to App Engine first generation runtimes (<= Go 1.9).

google/appengine_gen2_flex.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5+
//go:build !appengine
56
// +build !appengine
67

78
// This file applies to App Engine second generation runtimes (>= Go 1.11) and App Engine flexible.

0 commit comments

Comments
 (0)