diff options
author | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
---|---|---|
committer | Nathan Dench <ndenc2@gmail.com> | 2019-05-24 15:16:44 +1000 |
commit | 107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch) | |
tree | ca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/golang.org/x/oauth2 | |
parent | 844b5a68d8af4791755b8f0ad293cc99f5959183 (diff) | |
download | terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip |
Upgrade to 0.12
Diffstat (limited to 'vendor/golang.org/x/oauth2')
26 files changed, 2378 insertions, 0 deletions
diff --git a/vendor/golang.org/x/oauth2/.travis.yml b/vendor/golang.org/x/oauth2/.travis.yml new file mode 100644 index 0000000..fa139db --- /dev/null +++ b/vendor/golang.org/x/oauth2/.travis.yml | |||
@@ -0,0 +1,13 @@ | |||
1 | language: go | ||
2 | |||
3 | go: | ||
4 | - tip | ||
5 | |||
6 | install: | ||
7 | - export GOPATH="$HOME/gopath" | ||
8 | - mkdir -p "$GOPATH/src/golang.org/x" | ||
9 | - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2" | ||
10 | - go get -v -t -d golang.org/x/oauth2/... | ||
11 | |||
12 | script: | ||
13 | - go test -v golang.org/x/oauth2/... | ||
diff --git a/vendor/golang.org/x/oauth2/AUTHORS b/vendor/golang.org/x/oauth2/AUTHORS new file mode 100644 index 0000000..15167cd --- /dev/null +++ b/vendor/golang.org/x/oauth2/AUTHORS | |||
@@ -0,0 +1,3 @@ | |||
1 | # This source code refers to The Go Authors for copyright purposes. | ||
2 | # The master list of authors is in the main Go distribution, | ||
3 | # visible at http://tip.golang.org/AUTHORS. | ||
diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md new file mode 100644 index 0000000..dfbed62 --- /dev/null +++ b/vendor/golang.org/x/oauth2/CONTRIBUTING.md | |||
@@ -0,0 +1,26 @@ | |||
1 | # Contributing to Go | ||
2 | |||
3 | Go is an open source project. | ||
4 | |||
5 | It is the work of hundreds of contributors. We appreciate your help! | ||
6 | |||
7 | ## Filing issues | ||
8 | |||
9 | When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: | ||
10 | |||
11 | 1. What version of Go are you using (`go version`)? | ||
12 | 2. What operating system and processor architecture are you using? | ||
13 | 3. What did you do? | ||
14 | 4. What did you expect to see? | ||
15 | 5. What did you see instead? | ||
16 | |||
17 | General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. | ||
18 | The gophers there will answer or ask you to file an issue if you've tripped over a bug. | ||
19 | |||
20 | ## Contributing code | ||
21 | |||
22 | Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) | ||
23 | before sending patches. | ||
24 | |||
25 | Unless otherwise noted, the Go source files are distributed under | ||
26 | the BSD-style license found in the LICENSE file. | ||
diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTORS b/vendor/golang.org/x/oauth2/CONTRIBUTORS new file mode 100644 index 0000000..1c4577e --- /dev/null +++ b/vendor/golang.org/x/oauth2/CONTRIBUTORS | |||
@@ -0,0 +1,3 @@ | |||
1 | # This source code was written by the Go contributors. | ||
2 | # The master list of contributors is in the main Go distribution, | ||
3 | # visible at http://tip.golang.org/CONTRIBUTORS. | ||
diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE new file mode 100644 index 0000000..6a66aea --- /dev/null +++ b/vendor/golang.org/x/oauth2/LICENSE | |||
@@ -0,0 +1,27 @@ | |||
1 | Copyright (c) 2009 The Go Authors. All rights reserved. | ||
2 | |||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions are | ||
5 | met: | ||
6 | |||
7 | * Redistributions of source code must retain the above copyright | ||
8 | notice, this list of conditions and the following disclaimer. | ||
9 | * Redistributions in binary form must reproduce the above | ||
10 | copyright notice, this list of conditions and the following disclaimer | ||
11 | in the documentation and/or other materials provided with the | ||
12 | distribution. | ||
13 | * Neither the name of Google Inc. nor the names of its | ||
14 | contributors may be used to endorse or promote products derived from | ||
15 | this software without specific prior written permission. | ||
16 | |||
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md new file mode 100644 index 0000000..0f443e6 --- /dev/null +++ b/vendor/golang.org/x/oauth2/README.md | |||
@@ -0,0 +1,35 @@ | |||
1 | # OAuth2 for Go | ||
2 | |||
3 | [![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) | ||
5 | |||
6 | oauth2 package contains a client implementation for OAuth 2.0 spec. | ||
7 | |||
8 | ## Installation | ||
9 | |||
10 | ~~~~ | ||
11 | go get golang.org/x/oauth2 | ||
12 | ~~~~ | ||
13 | |||
14 | Or you can manually git clone the repository to | ||
15 | `$(go env GOPATH)/src/golang.org/x/oauth2`. | ||
16 | |||
17 | See godoc for further documentation and examples. | ||
18 | |||
19 | * [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2) | ||
20 | * [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google) | ||
21 | |||
22 | ## Policy for new packages | ||
23 | |||
24 | We no longer accept new provider-specific packages in this repo. For | ||
25 | defining provider endpoints and provider-specific OAuth2 behavior, we | ||
26 | encourage you to create packages elsewhere. We'll keep the existing | ||
27 | packages for compatibility. | ||
28 | |||
29 | ## Report Issues / Send Patches | ||
30 | |||
31 | This repository uses Gerrit for code changes. To learn how to submit changes to | ||
32 | this repository, see https://golang.org/doc/contribute.html. | ||
33 | |||
34 | The main issue tracker for the oauth2 repository is located at | ||
35 | https://github.com/golang/oauth2/issues. | ||
diff --git a/vendor/golang.org/x/oauth2/go.mod b/vendor/golang.org/x/oauth2/go.mod new file mode 100644 index 0000000..b345781 --- /dev/null +++ b/vendor/golang.org/x/oauth2/go.mod | |||
@@ -0,0 +1,10 @@ | |||
1 | module golang.org/x/oauth2 | ||
2 | |||
3 | go 1.11 | ||
4 | |||
5 | require ( | ||
6 | cloud.google.com/go v0.34.0 | ||
7 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e | ||
8 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect | ||
9 | google.golang.org/appengine v1.4.0 | ||
10 | ) | ||
diff --git a/vendor/golang.org/x/oauth2/go.sum b/vendor/golang.org/x/oauth2/go.sum new file mode 100644 index 0000000..6f0079b --- /dev/null +++ b/vendor/golang.org/x/oauth2/go.sum | |||
@@ -0,0 +1,12 @@ | |||
1 | cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= | ||
2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | ||
3 | github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= | ||
4 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||
5 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
6 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= | ||
7 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
8 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= | ||
9 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
10 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
11 | google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= | ||
12 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | ||
diff --git a/vendor/golang.org/x/oauth2/google/appengine.go b/vendor/golang.org/x/oauth2/google/appengine.go new file mode 100644 index 0000000..feb1157 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/appengine.go | |||
@@ -0,0 +1,38 @@ | |||
1 | // Copyright 2014 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 google | ||
6 | |||
7 | import ( | ||
8 | "context" | ||
9 | "time" | ||
10 | |||
11 | "golang.org/x/oauth2" | ||
12 | ) | ||
13 | |||
14 | // Set at init time by appengine_gen1.go. If nil, we're not on App Engine standard first generation (<= Go 1.9) or App Engine flexible. | ||
15 | var appengineTokenFunc func(c context.Context, scopes ...string) (token string, expiry time.Time, err error) | ||
16 | |||
17 | // Set at init time by appengine_gen1.go. If nil, we're not on App Engine standard first generation (<= Go 1.9) or App Engine flexible. | ||
18 | var appengineAppIDFunc func(c context.Context) string | ||
19 | |||
20 | // AppEngineTokenSource returns a token source that fetches tokens from either | ||
21 | // the current application's service account or from the metadata server, | ||
22 | // depending on the App Engine environment. See below for environment-specific | ||
23 | // details. If you are implementing a 3-legged OAuth 2.0 flow on App Engine that | ||
24 | // involves user accounts, see oauth2.Config instead. | ||
25 | // | ||
26 | // First generation App Engine runtimes (<= Go 1.9): | ||
27 | // AppEngineTokenSource returns a token source that fetches tokens issued to the | ||
28 | // current App Engine application's service account. The provided context must have | ||
29 | // come from appengine.NewContext. | ||
30 | // | ||
31 | // Second generation App Engine runtimes (>= Go 1.11) and App Engine flexible: | ||
32 | // AppEngineTokenSource is DEPRECATED on second generation runtimes and on the | ||
33 | // flexible environment. It delegates to ComputeTokenSource, and the provided | ||
34 | // context and scopes are not used. Please use DefaultTokenSource (or ComputeTokenSource, | ||
35 | // which DefaultTokenSource will use in this case) instead. | ||
36 | func AppEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource { | ||
37 | return appEngineTokenSource(ctx, scope...) | ||
38 | } | ||
diff --git a/vendor/golang.org/x/oauth2/google/appengine_gen1.go b/vendor/golang.org/x/oauth2/google/appengine_gen1.go new file mode 100644 index 0000000..83dacac --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/appengine_gen1.go | |||
@@ -0,0 +1,77 @@ | |||
1 | // Copyright 2018 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 | // +build appengine | ||
6 | |||
7 | // This file applies to App Engine first generation runtimes (<= Go 1.9). | ||
8 | |||
9 | package google | ||
10 | |||
11 | import ( | ||
12 | "context" | ||
13 | "sort" | ||
14 | "strings" | ||
15 | "sync" | ||
16 | |||
17 | "golang.org/x/oauth2" | ||
18 | "google.golang.org/appengine" | ||
19 | ) | ||
20 | |||
21 | func init() { | ||
22 | appengineTokenFunc = appengine.AccessToken | ||
23 | appengineAppIDFunc = appengine.AppID | ||
24 | } | ||
25 | |||
26 | // See comment on AppEngineTokenSource in appengine.go. | ||
27 | func appEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource { | ||
28 | scopes := append([]string{}, scope...) | ||
29 | sort.Strings(scopes) | ||
30 | return &gaeTokenSource{ | ||
31 | ctx: ctx, | ||
32 | scopes: scopes, | ||
33 | key: strings.Join(scopes, " "), | ||
34 | } | ||
35 | } | ||
36 | |||
37 | // aeTokens helps the fetched tokens to be reused until their expiration. | ||
38 | var ( | ||
39 | aeTokensMu sync.Mutex | ||
40 | aeTokens = make(map[string]*tokenLock) // key is space-separated scopes | ||
41 | ) | ||
42 | |||
43 | type tokenLock struct { | ||
44 | mu sync.Mutex // guards t; held while fetching or updating t | ||
45 | t *oauth2.Token | ||
46 | } | ||
47 | |||
48 | type gaeTokenSource struct { | ||
49 | ctx context.Context | ||
50 | scopes []string | ||
51 | key string // to aeTokens map; space-separated scopes | ||
52 | } | ||
53 | |||
54 | func (ts *gaeTokenSource) Token() (*oauth2.Token, error) { | ||
55 | aeTokensMu.Lock() | ||
56 | tok, ok := aeTokens[ts.key] | ||
57 | if !ok { | ||
58 | tok = &tokenLock{} | ||
59 | aeTokens[ts.key] = tok | ||
60 | } | ||
61 | aeTokensMu.Unlock() | ||
62 | |||
63 | tok.mu.Lock() | ||
64 | defer tok.mu.Unlock() | ||
65 | if tok.t.Valid() { | ||
66 | return tok.t, nil | ||
67 | } | ||
68 | access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...) | ||
69 | if err != nil { | ||
70 | return nil, err | ||
71 | } | ||
72 | tok.t = &oauth2.Token{ | ||
73 | AccessToken: access, | ||
74 | Expiry: exp, | ||
75 | } | ||
76 | return tok.t, nil | ||
77 | } | ||
diff --git a/vendor/golang.org/x/oauth2/google/appengine_gen2_flex.go b/vendor/golang.org/x/oauth2/google/appengine_gen2_flex.go new file mode 100644 index 0000000..04c2c22 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/appengine_gen2_flex.go | |||
@@ -0,0 +1,27 @@ | |||
1 | // Copyright 2018 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 | // +build !appengine | ||
6 | |||
7 | // This file applies to App Engine second generation runtimes (>= Go 1.11) and App Engine flexible. | ||
8 | |||
9 | package google | ||
10 | |||
11 | import ( | ||
12 | "context" | ||
13 | "log" | ||
14 | "sync" | ||
15 | |||
16 | "golang.org/x/oauth2" | ||
17 | ) | ||
18 | |||
19 | var logOnce sync.Once // only spam about deprecation once | ||
20 | |||
21 | // See comment on AppEngineTokenSource in appengine.go. | ||
22 | func appEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource { | ||
23 | logOnce.Do(func() { | ||
24 | log.Print("google: AppEngineTokenSource is deprecated on App Engine standard second generation runtimes (>= Go 1.11) and App Engine flexible. Please use DefaultTokenSource or ComputeTokenSource.") | ||
25 | }) | ||
26 | return ComputeTokenSource("") | ||
27 | } | ||
diff --git a/vendor/golang.org/x/oauth2/google/default.go b/vendor/golang.org/x/oauth2/google/default.go new file mode 100644 index 0000000..5087d84 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/default.go | |||
@@ -0,0 +1,155 @@ | |||
1 | // Copyright 2015 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 google | ||
6 | |||
7 | import ( | ||
8 | "context" | ||
9 | "encoding/json" | ||
10 | "fmt" | ||
11 | "io/ioutil" | ||
12 | "net/http" | ||
13 | "os" | ||
14 | "path/filepath" | ||
15 | "runtime" | ||
16 | |||
17 | "cloud.google.com/go/compute/metadata" | ||
18 | "golang.org/x/oauth2" | ||
19 | ) | ||
20 | |||
21 | // Credentials holds Google credentials, including "Application Default Credentials". | ||
22 | // For more details, see: | ||
23 | // https://developers.google.com/accounts/docs/application-default-credentials | ||
24 | type Credentials struct { | ||
25 | ProjectID string // may be empty | ||
26 | TokenSource oauth2.TokenSource | ||
27 | |||
28 | // JSON contains the raw bytes from a JSON credentials file. | ||
29 | // This field may be nil if authentication is provided by the | ||
30 | // environment and not with a credentials file, e.g. when code is | ||
31 | // running on Google Cloud Platform. | ||
32 | JSON []byte | ||
33 | } | ||
34 | |||
35 | // DefaultCredentials is the old name of Credentials. | ||
36 | // | ||
37 | // Deprecated: use Credentials instead. | ||
38 | type DefaultCredentials = Credentials | ||
39 | |||
40 | // DefaultClient returns an HTTP Client that uses the | ||
41 | // DefaultTokenSource to obtain authentication credentials. | ||
42 | func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) { | ||
43 | ts, err := DefaultTokenSource(ctx, scope...) | ||
44 | if err != nil { | ||
45 | return nil, err | ||
46 | } | ||
47 | return oauth2.NewClient(ctx, ts), nil | ||
48 | } | ||
49 | |||
50 | // DefaultTokenSource returns the token source for | ||
51 | // "Application Default Credentials". | ||
52 | // It is a shortcut for FindDefaultCredentials(ctx, scope).TokenSource. | ||
53 | func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) { | ||
54 | creds, err := FindDefaultCredentials(ctx, scope...) | ||
55 | if err != nil { | ||
56 | return nil, err | ||
57 | } | ||
58 | return creds.TokenSource, nil | ||
59 | } | ||
60 | |||
61 | // FindDefaultCredentials searches for "Application Default Credentials". | ||
62 | // | ||
63 | // It looks for credentials in the following places, | ||
64 | // preferring the first location found: | ||
65 | // | ||
66 | // 1. A JSON file whose path is specified by the | ||
67 | // GOOGLE_APPLICATION_CREDENTIALS environment variable. | ||
68 | // 2. A JSON file in a location known to the gcloud command-line tool. | ||
69 | // On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. | ||
70 | // On other systems, $HOME/.config/gcloud/application_default_credentials.json. | ||
71 | // 3. On Google App Engine standard first generation runtimes (<= Go 1.9) it uses | ||
72 | // the appengine.AccessToken function. | ||
73 | // 4. On Google Compute Engine, Google App Engine standard second generation runtimes | ||
74 | // (>= Go 1.11), and Google App Engine flexible environment, it fetches | ||
75 | // credentials from the metadata server. | ||
76 | // (In this final case any provided scopes are ignored.) | ||
77 | func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials, error) { | ||
78 | // First, try the environment variable. | ||
79 | const envVar = "GOOGLE_APPLICATION_CREDENTIALS" | ||
80 | if filename := os.Getenv(envVar); filename != "" { | ||
81 | creds, err := readCredentialsFile(ctx, filename, scopes) | ||
82 | if err != nil { | ||
83 | return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err) | ||
84 | } | ||
85 | return creds, nil | ||
86 | } | ||
87 | |||
88 | // Second, try a well-known file. | ||
89 | filename := wellKnownFile() | ||
90 | if creds, err := readCredentialsFile(ctx, filename, scopes); err == nil { | ||
91 | return creds, nil | ||
92 | } else if !os.IsNotExist(err) { | ||
93 | return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err) | ||
94 | } | ||
95 | |||
96 | // Third, if we're on a Google App Engine standard first generation runtime (<= Go 1.9) | ||
97 | // use those credentials. App Engine standard second generation runtimes (>= Go 1.11) | ||
98 | // and App Engine flexible use ComputeTokenSource and the metadata server. | ||
99 | if appengineTokenFunc != nil { | ||
100 | return &DefaultCredentials{ | ||
101 | ProjectID: appengineAppIDFunc(ctx), | ||
102 | TokenSource: AppEngineTokenSource(ctx, scopes...), | ||
103 | }, nil | ||
104 | } | ||
105 | |||
106 | // Fourth, if we're on Google Compute Engine, an App Engine standard second generation runtime, | ||
107 | // or App Engine flexible, use the metadata server. | ||
108 | if metadata.OnGCE() { | ||
109 | id, _ := metadata.ProjectID() | ||
110 | return &DefaultCredentials{ | ||
111 | ProjectID: id, | ||
112 | TokenSource: ComputeTokenSource(""), | ||
113 | }, nil | ||
114 | } | ||
115 | |||
116 | // None are found; return helpful error. | ||
117 | const url = "https://developers.google.com/accounts/docs/application-default-credentials" | ||
118 | return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url) | ||
119 | } | ||
120 | |||
121 | // CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can | ||
122 | // represent either a Google Developers Console client_credentials.json file (as in | ||
123 | // ConfigFromJSON) or a Google Developers service account key file (as in | ||
124 | // JWTConfigFromJSON). | ||
125 | func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*Credentials, error) { | ||
126 | var f credentialsFile | ||
127 | if err := json.Unmarshal(jsonData, &f); err != nil { | ||
128 | return nil, err | ||
129 | } | ||
130 | ts, err := f.tokenSource(ctx, append([]string(nil), scopes...)) | ||
131 | if err != nil { | ||
132 | return nil, err | ||
133 | } | ||
134 | return &DefaultCredentials{ | ||
135 | ProjectID: f.ProjectID, | ||
136 | TokenSource: ts, | ||
137 | JSON: jsonData, | ||
138 | }, nil | ||
139 | } | ||
140 | |||
141 | func wellKnownFile() string { | ||
142 | const f = "application_default_credentials.json" | ||
143 | if runtime.GOOS == "windows" { | ||
144 | return filepath.Join(os.Getenv("APPDATA"), "gcloud", f) | ||
145 | } | ||
146 | return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f) | ||
147 | } | ||
148 | |||
149 | func readCredentialsFile(ctx context.Context, filename string, scopes []string) (*DefaultCredentials, error) { | ||
150 | b, err := ioutil.ReadFile(filename) | ||
151 | if err != nil { | ||
152 | return nil, err | ||
153 | } | ||
154 | return CredentialsFromJSON(ctx, b, scopes...) | ||
155 | } | ||
diff --git a/vendor/golang.org/x/oauth2/google/doc.go b/vendor/golang.org/x/oauth2/google/doc.go new file mode 100644 index 0000000..73be629 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/doc.go | |||
@@ -0,0 +1,40 @@ | |||
1 | // Copyright 2018 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 google provides support for making OAuth2 authorized and authenticated | ||
6 | // HTTP requests to Google APIs. It supports the Web server flow, client-side | ||
7 | // credentials, service accounts, Google Compute Engine service accounts, and Google | ||
8 | // App Engine service accounts. | ||
9 | // | ||
10 | // A brief overview of the package follows. For more information, please read | ||
11 | // https://developers.google.com/accounts/docs/OAuth2 | ||
12 | // and | ||
13 | // https://developers.google.com/accounts/docs/application-default-credentials. | ||
14 | // | ||
15 | // OAuth2 Configs | ||
16 | // | ||
17 | // Two functions in this package return golang.org/x/oauth2.Config values from Google credential | ||
18 | // data. Google supports two JSON formats for OAuth2 credentials: one is handled by ConfigFromJSON, | ||
19 | // the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or | ||
20 | // create an http.Client. | ||
21 | // | ||
22 | // | ||
23 | // Credentials | ||
24 | // | ||
25 | // The Credentials type represents Google credentials, including Application Default | ||
26 | // Credentials. | ||
27 | // | ||
28 | // Use FindDefaultCredentials to obtain Application Default Credentials. | ||
29 | // FindDefaultCredentials looks in some well-known places for a credentials file, and | ||
30 | // will call AppEngineTokenSource or ComputeTokenSource as needed. | ||
31 | // | ||
32 | // DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials, | ||
33 | // then use the credentials to construct an http.Client or an oauth2.TokenSource. | ||
34 | // | ||
35 | // Use CredentialsFromJSON to obtain credentials from either of the two JSON formats | ||
36 | // described in OAuth2 Configs, above. The TokenSource in the returned value is the | ||
37 | // same as the one obtained from the oauth2.Config returned from ConfigFromJSON or | ||
38 | // JWTConfigFromJSON, but the Credentials may contain additional information | ||
39 | // that is useful is some circumstances. | ||
40 | package google // import "golang.org/x/oauth2/google" | ||
diff --git a/vendor/golang.org/x/oauth2/google/google.go b/vendor/golang.org/x/oauth2/google/google.go new file mode 100644 index 0000000..4b0b547 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/google.go | |||
@@ -0,0 +1,193 @@ | |||
1 | // Copyright 2014 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 google | ||
6 | |||
7 | import ( | ||
8 | "context" | ||
9 | "encoding/json" | ||
10 | "errors" | ||
11 | "fmt" | ||
12 | "strings" | ||
13 | "time" | ||
14 | |||
15 | "cloud.google.com/go/compute/metadata" | ||
16 | "golang.org/x/oauth2" | ||
17 | "golang.org/x/oauth2/jwt" | ||
18 | ) | ||
19 | |||
20 | // Endpoint is Google's OAuth 2.0 endpoint. | ||
21 | var Endpoint = oauth2.Endpoint{ | ||
22 | AuthURL: "https://accounts.google.com/o/oauth2/auth", | ||
23 | TokenURL: "https://accounts.google.com/o/oauth2/token", | ||
24 | AuthStyle: oauth2.AuthStyleInParams, | ||
25 | } | ||
26 | |||
27 | // JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow. | ||
28 | const JWTTokenURL = "https://accounts.google.com/o/oauth2/token" | ||
29 | |||
30 | // ConfigFromJSON uses a Google Developers Console client_credentials.json | ||
31 | // file to construct a config. | ||
32 | // client_credentials.json can be downloaded from | ||
33 | // https://console.developers.google.com, under "Credentials". Download the Web | ||
34 | // application credentials in the JSON format and provide the contents of the | ||
35 | // file as jsonKey. | ||
36 | func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) { | ||
37 | type cred struct { | ||
38 | ClientID string `json:"client_id"` | ||
39 | ClientSecret string `json:"client_secret"` | ||
40 | RedirectURIs []string `json:"redirect_uris"` | ||
41 | AuthURI string `json:"auth_uri"` | ||
42 | TokenURI string `json:"token_uri"` | ||
43 | } | ||
44 | var j struct { | ||
45 | Web *cred `json:"web"` | ||
46 | Installed *cred `json:"installed"` | ||
47 | } | ||
48 | if err := json.Unmarshal(jsonKey, &j); err != nil { | ||
49 | return nil, err | ||
50 | } | ||
51 | var c *cred | ||
52 | switch { | ||
53 | case j.Web != nil: | ||
54 | c = j.Web | ||
55 | case j.Installed != nil: | ||
56 | c = j.Installed | ||
57 | default: | ||
58 | return nil, fmt.Errorf("oauth2/google: no credentials found") | ||
59 | } | ||
60 | if len(c.RedirectURIs) < 1 { | ||
61 | return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json") | ||
62 | } | ||
63 | return &oauth2.Config{ | ||
64 | ClientID: c.ClientID, | ||
65 | ClientSecret: c.ClientSecret, | ||
66 | RedirectURL: c.RedirectURIs[0], | ||
67 | Scopes: scope, | ||
68 | Endpoint: oauth2.Endpoint{ | ||
69 | AuthURL: c.AuthURI, | ||
70 | TokenURL: c.TokenURI, | ||
71 | }, | ||
72 | }, nil | ||
73 | } | ||
74 | |||
75 | // JWTConfigFromJSON uses a Google Developers service account JSON key file to read | ||
76 | // the credentials that authorize and authenticate the requests. | ||
77 | // Create a service account on "Credentials" for your project at | ||
78 | // https://console.developers.google.com to download a JSON key file. | ||
79 | func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) { | ||
80 | var f credentialsFile | ||
81 | if err := json.Unmarshal(jsonKey, &f); err != nil { | ||
82 | return nil, err | ||
83 | } | ||
84 | if f.Type != serviceAccountKey { | ||
85 | return nil, fmt.Errorf("google: read JWT from JSON credentials: 'type' field is %q (expected %q)", f.Type, serviceAccountKey) | ||
86 | } | ||
87 | scope = append([]string(nil), scope...) // copy | ||
88 | return f.jwtConfig(scope), nil | ||
89 | } | ||
90 | |||
91 | // JSON key file types. | ||
92 | const ( | ||
93 | serviceAccountKey = "service_account" | ||
94 | userCredentialsKey = "authorized_user" | ||
95 | ) | ||
96 | |||
97 | // credentialsFile is the unmarshalled representation of a credentials file. | ||
98 | type credentialsFile struct { | ||
99 | Type string `json:"type"` // serviceAccountKey or userCredentialsKey | ||
100 | |||
101 | // Service Account fields | ||
102 | ClientEmail string `json:"client_email"` | ||
103 | PrivateKeyID string `json:"private_key_id"` | ||
104 | PrivateKey string `json:"private_key"` | ||
105 | TokenURL string `json:"token_uri"` | ||
106 | ProjectID string `json:"project_id"` | ||
107 | |||
108 | // User Credential fields | ||
109 | // (These typically come from gcloud auth.) | ||
110 | ClientSecret string `json:"client_secret"` | ||
111 | ClientID string `json:"client_id"` | ||
112 | RefreshToken string `json:"refresh_token"` | ||
113 | } | ||
114 | |||
115 | func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config { | ||
116 | cfg := &jwt.Config{ | ||
117 | Email: f.ClientEmail, | ||
118 | PrivateKey: []byte(f.PrivateKey), | ||
119 | PrivateKeyID: f.PrivateKeyID, | ||
120 | Scopes: scopes, | ||
121 | TokenURL: f.TokenURL, | ||
122 | } | ||
123 | if cfg.TokenURL == "" { | ||
124 | cfg.TokenURL = JWTTokenURL | ||
125 | } | ||
126 | return cfg | ||
127 | } | ||
128 | |||
129 | func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oauth2.TokenSource, error) { | ||
130 | switch f.Type { | ||
131 | case serviceAccountKey: | ||
132 | cfg := f.jwtConfig(scopes) | ||
133 | return cfg.TokenSource(ctx), nil | ||
134 | case userCredentialsKey: | ||
135 | cfg := &oauth2.Config{ | ||
136 | ClientID: f.ClientID, | ||
137 | ClientSecret: f.ClientSecret, | ||
138 | Scopes: scopes, | ||
139 | Endpoint: Endpoint, | ||
140 | } | ||
141 | tok := &oauth2.Token{RefreshToken: f.RefreshToken} | ||
142 | return cfg.TokenSource(ctx, tok), nil | ||
143 | case "": | ||
144 | return nil, errors.New("missing 'type' field in credentials") | ||
145 | default: | ||
146 | return nil, fmt.Errorf("unknown credential type: %q", f.Type) | ||
147 | } | ||
148 | } | ||
149 | |||
150 | // ComputeTokenSource returns a token source that fetches access tokens | ||
151 | // from Google Compute Engine (GCE)'s metadata server. It's only valid to use | ||
152 | // this token source if your program is running on a GCE instance. | ||
153 | // If no account is specified, "default" is used. | ||
154 | // Further information about retrieving access tokens from the GCE metadata | ||
155 | // server can be found at https://cloud.google.com/compute/docs/authentication. | ||
156 | func ComputeTokenSource(account string) oauth2.TokenSource { | ||
157 | return oauth2.ReuseTokenSource(nil, computeSource{account: account}) | ||
158 | } | ||
159 | |||
160 | type computeSource struct { | ||
161 | account string | ||
162 | } | ||
163 | |||
164 | func (cs computeSource) Token() (*oauth2.Token, error) { | ||
165 | if !metadata.OnGCE() { | ||
166 | return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE") | ||
167 | } | ||
168 | acct := cs.account | ||
169 | if acct == "" { | ||
170 | acct = "default" | ||
171 | } | ||
172 | tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token") | ||
173 | if err != nil { | ||
174 | return nil, err | ||
175 | } | ||
176 | var res struct { | ||
177 | AccessToken string `json:"access_token"` | ||
178 | ExpiresInSec int `json:"expires_in"` | ||
179 | TokenType string `json:"token_type"` | ||
180 | } | ||
181 | err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res) | ||
182 | if err != nil { | ||
183 | return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err) | ||
184 | } | ||
185 | if res.ExpiresInSec == 0 || res.AccessToken == "" { | ||
186 | return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata") | ||
187 | } | ||
188 | return &oauth2.Token{ | ||
189 | AccessToken: res.AccessToken, | ||
190 | TokenType: res.TokenType, | ||
191 | Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second), | ||
192 | }, nil | ||
193 | } | ||
diff --git a/vendor/golang.org/x/oauth2/google/jwt.go b/vendor/golang.org/x/oauth2/google/jwt.go new file mode 100644 index 0000000..b0fdb3a --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/jwt.go | |||
@@ -0,0 +1,74 @@ | |||
1 | // Copyright 2015 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 google | ||
6 | |||
7 | import ( | ||
8 | "crypto/rsa" | ||
9 | "fmt" | ||
10 | "time" | ||
11 | |||
12 | "golang.org/x/oauth2" | ||
13 | "golang.org/x/oauth2/internal" | ||
14 | "golang.org/x/oauth2/jws" | ||
15 | ) | ||
16 | |||
17 | // JWTAccessTokenSourceFromJSON uses a Google Developers service account JSON | ||
18 | // key file to read the credentials that authorize and authenticate the | ||
19 | // requests, and returns a TokenSource that does not use any OAuth2 flow but | ||
20 | // instead creates a JWT and sends that as the access token. | ||
21 | // The audience is typically a URL that specifies the scope of the credentials. | ||
22 | // | ||
23 | // Note that this is not a standard OAuth flow, but rather an | ||
24 | // optimization supported by a few Google services. | ||
25 | // Unless you know otherwise, you should use JWTConfigFromJSON instead. | ||
26 | func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.TokenSource, error) { | ||
27 | cfg, err := JWTConfigFromJSON(jsonKey) | ||
28 | if err != nil { | ||
29 | return nil, fmt.Errorf("google: could not parse JSON key: %v", err) | ||
30 | } | ||
31 | pk, err := internal.ParseKey(cfg.PrivateKey) | ||
32 | if err != nil { | ||
33 | return nil, fmt.Errorf("google: could not parse key: %v", err) | ||
34 | } | ||
35 | ts := &jwtAccessTokenSource{ | ||
36 | email: cfg.Email, | ||
37 | audience: audience, | ||
38 | pk: pk, | ||
39 | pkID: cfg.PrivateKeyID, | ||
40 | } | ||
41 | tok, err := ts.Token() | ||
42 | if err != nil { | ||
43 | return nil, err | ||
44 | } | ||
45 | return oauth2.ReuseTokenSource(tok, ts), nil | ||
46 | } | ||
47 | |||
48 | type jwtAccessTokenSource struct { | ||
49 | email, audience string | ||
50 | pk *rsa.PrivateKey | ||
51 | pkID string | ||
52 | } | ||
53 | |||
54 | func (ts *jwtAccessTokenSource) Token() (*oauth2.Token, error) { | ||
55 | iat := time.Now() | ||
56 | exp := iat.Add(time.Hour) | ||
57 | cs := &jws.ClaimSet{ | ||
58 | Iss: ts.email, | ||
59 | Sub: ts.email, | ||
60 | Aud: ts.audience, | ||
61 | Iat: iat.Unix(), | ||
62 | Exp: exp.Unix(), | ||
63 | } | ||
64 | hdr := &jws.Header{ | ||
65 | Algorithm: "RS256", | ||
66 | Typ: "JWT", | ||
67 | KeyID: string(ts.pkID), | ||
68 | } | ||
69 | msg, err := jws.Encode(hdr, cs, ts.pk) | ||
70 | if err != nil { | ||
71 | return nil, fmt.Errorf("google: could not encode JWT: %v", err) | ||
72 | } | ||
73 | return &oauth2.Token{AccessToken: msg, TokenType: "Bearer", Expiry: exp}, nil | ||
74 | } | ||
diff --git a/vendor/golang.org/x/oauth2/google/sdk.go b/vendor/golang.org/x/oauth2/google/sdk.go new file mode 100644 index 0000000..456224b --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/sdk.go | |||
@@ -0,0 +1,201 @@ | |||
1 | // Copyright 2015 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 google | ||
6 | |||
7 | import ( | ||
8 | "bufio" | ||
9 | "context" | ||
10 | "encoding/json" | ||
11 | "errors" | ||
12 | "fmt" | ||
13 | "io" | ||
14 | "net/http" | ||
15 | "os" | ||
16 | "os/user" | ||
17 | "path/filepath" | ||
18 | "runtime" | ||
19 | "strings" | ||
20 | "time" | ||
21 | |||
22 | "golang.org/x/oauth2" | ||
23 | ) | ||
24 | |||
25 | type sdkCredentials struct { | ||
26 | Data []struct { | ||
27 | Credential struct { | ||
28 | ClientID string `json:"client_id"` | ||
29 | ClientSecret string `json:"client_secret"` | ||
30 | AccessToken string `json:"access_token"` | ||
31 | RefreshToken string `json:"refresh_token"` | ||
32 | TokenExpiry *time.Time `json:"token_expiry"` | ||
33 | } `json:"credential"` | ||
34 | Key struct { | ||
35 | Account string `json:"account"` | ||
36 | Scope string `json:"scope"` | ||
37 | } `json:"key"` | ||
38 | } | ||
39 | } | ||
40 | |||
41 | // An SDKConfig provides access to tokens from an account already | ||
42 | // authorized via the Google Cloud SDK. | ||
43 | type SDKConfig struct { | ||
44 | conf oauth2.Config | ||
45 | initialToken *oauth2.Token | ||
46 | } | ||
47 | |||
48 | // NewSDKConfig creates an SDKConfig for the given Google Cloud SDK | ||
49 | // account. If account is empty, the account currently active in | ||
50 | // Google Cloud SDK properties is used. | ||
51 | // Google Cloud SDK credentials must be created by running `gcloud auth` | ||
52 | // before using this function. | ||
53 | // The Google Cloud SDK is available at https://cloud.google.com/sdk/. | ||
54 | func NewSDKConfig(account string) (*SDKConfig, error) { | ||
55 | configPath, err := sdkConfigPath() | ||
56 | if err != nil { | ||
57 | return nil, fmt.Errorf("oauth2/google: error getting SDK config path: %v", err) | ||
58 | } | ||
59 | credentialsPath := filepath.Join(configPath, "credentials") | ||
60 | f, err := os.Open(credentialsPath) | ||
61 | if err != nil { | ||
62 | return nil, fmt.Errorf("oauth2/google: failed to load SDK credentials: %v", err) | ||
63 | } | ||
64 | defer f.Close() | ||
65 | |||
66 | var c sdkCredentials | ||
67 | if err := json.NewDecoder(f).Decode(&c); err != nil { | ||
68 | return nil, fmt.Errorf("oauth2/google: failed to decode SDK credentials from %q: %v", credentialsPath, err) | ||
69 | } | ||
70 | if len(c.Data) == 0 { | ||
71 | return nil, fmt.Errorf("oauth2/google: no credentials found in %q, run `gcloud auth login` to create one", credentialsPath) | ||
72 | } | ||
73 | if account == "" { | ||
74 | propertiesPath := filepath.Join(configPath, "properties") | ||
75 | f, err := os.Open(propertiesPath) | ||
76 | if err != nil { | ||
77 | return nil, fmt.Errorf("oauth2/google: failed to load SDK properties: %v", err) | ||
78 | } | ||
79 | defer f.Close() | ||
80 | ini, err := parseINI(f) | ||
81 | if err != nil { | ||
82 | return nil, fmt.Errorf("oauth2/google: failed to parse SDK properties %q: %v", propertiesPath, err) | ||
83 | } | ||
84 | core, ok := ini["core"] | ||
85 | if !ok { | ||
86 | return nil, fmt.Errorf("oauth2/google: failed to find [core] section in %v", ini) | ||
87 | } | ||
88 | active, ok := core["account"] | ||
89 | if !ok { | ||
90 | return nil, fmt.Errorf("oauth2/google: failed to find %q attribute in %v", "account", core) | ||
91 | } | ||
92 | account = active | ||
93 | } | ||
94 | |||
95 | for _, d := range c.Data { | ||
96 | if account == "" || d.Key.Account == account { | ||
97 | if d.Credential.AccessToken == "" && d.Credential.RefreshToken == "" { | ||
98 | return nil, fmt.Errorf("oauth2/google: no token available for account %q", account) | ||
99 | } | ||
100 | var expiry time.Time | ||
101 | if d.Credential.TokenExpiry != nil { | ||
102 | expiry = *d.Credential.TokenExpiry | ||
103 | } | ||
104 | return &SDKConfig{ | ||
105 | conf: oauth2.Config{ | ||
106 | ClientID: d.Credential.ClientID, | ||
107 | ClientSecret: d.Credential.ClientSecret, | ||
108 | Scopes: strings.Split(d.Key.Scope, " "), | ||
109 | Endpoint: Endpoint, | ||
110 | RedirectURL: "oob", | ||
111 | }, | ||
112 | initialToken: &oauth2.Token{ | ||
113 | AccessToken: d.Credential.AccessToken, | ||
114 | RefreshToken: d.Credential.RefreshToken, | ||
115 | Expiry: expiry, | ||
116 | }, | ||
117 | }, nil | ||
118 | } | ||
119 | } | ||
120 | return nil, fmt.Errorf("oauth2/google: no such credentials for account %q", account) | ||
121 | } | ||
122 | |||
123 | // Client returns an HTTP client using Google Cloud SDK credentials to | ||
124 | // authorize requests. The token will auto-refresh as necessary. The | ||
125 | // underlying http.RoundTripper will be obtained using the provided | ||
126 | // context. The returned client and its Transport should not be | ||
127 | // modified. | ||
128 | func (c *SDKConfig) Client(ctx context.Context) *http.Client { | ||
129 | return &http.Client{ | ||
130 | Transport: &oauth2.Transport{ | ||
131 | Source: c.TokenSource(ctx), | ||
132 | }, | ||
133 | } | ||
134 | } | ||
135 | |||
136 | // TokenSource returns an oauth2.TokenSource that retrieve tokens from | ||
137 | // Google Cloud SDK credentials using the provided context. | ||
138 | // It will returns the current access token stored in the credentials, | ||
139 | // and refresh it when it expires, but it won't update the credentials | ||
140 | // with the new access token. | ||
141 | func (c *SDKConfig) TokenSource(ctx context.Context) oauth2.TokenSource { | ||
142 | return c.conf.TokenSource(ctx, c.initialToken) | ||
143 | } | ||
144 | |||
145 | // Scopes are the OAuth 2.0 scopes the current account is authorized for. | ||
146 | func (c *SDKConfig) Scopes() []string { | ||
147 | return c.conf.Scopes | ||
148 | } | ||
149 | |||
150 | func parseINI(ini io.Reader) (map[string]map[string]string, error) { | ||
151 | result := map[string]map[string]string{ | ||
152 | "": {}, // root section | ||
153 | } | ||
154 | scanner := bufio.NewScanner(ini) | ||
155 | currentSection := "" | ||
156 | for scanner.Scan() { | ||
157 | line := strings.TrimSpace(scanner.Text()) | ||
158 | if strings.HasPrefix(line, ";") { | ||
159 | // comment. | ||
160 | continue | ||
161 | } | ||
162 | if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { | ||
163 | currentSection = strings.TrimSpace(line[1 : len(line)-1]) | ||
164 | result[currentSection] = map[string]string{} | ||
165 | continue | ||
166 | } | ||
167 | parts := strings.SplitN(line, "=", 2) | ||
168 | if len(parts) == 2 && parts[0] != "" { | ||
169 | result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) | ||
170 | } | ||
171 | } | ||
172 | if err := scanner.Err(); err != nil { | ||
173 | return nil, fmt.Errorf("error scanning ini: %v", err) | ||
174 | } | ||
175 | return result, nil | ||
176 | } | ||
177 | |||
178 | // sdkConfigPath tries to guess where the gcloud config is located. | ||
179 | // It can be overridden during tests. | ||
180 | var sdkConfigPath = func() (string, error) { | ||
181 | if runtime.GOOS == "windows" { | ||
182 | return filepath.Join(os.Getenv("APPDATA"), "gcloud"), nil | ||
183 | } | ||
184 | homeDir := guessUnixHomeDir() | ||
185 | if homeDir == "" { | ||
186 | return "", errors.New("unable to get current user home directory: os/user lookup failed; $HOME is empty") | ||
187 | } | ||
188 | return filepath.Join(homeDir, ".config", "gcloud"), nil | ||
189 | } | ||
190 | |||
191 | func guessUnixHomeDir() string { | ||
192 | // Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470 | ||
193 | if v := os.Getenv("HOME"); v != "" { | ||
194 | return v | ||
195 | } | ||
196 | // Else, fall back to user.Current: | ||
197 | if u, err := user.Current(); err == nil { | ||
198 | return u.HomeDir | ||
199 | } | ||
200 | return "" | ||
201 | } | ||
diff --git a/vendor/golang.org/x/oauth2/internal/client_appengine.go b/vendor/golang.org/x/oauth2/internal/client_appengine.go new file mode 100644 index 0000000..7434871 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/client_appengine.go | |||
@@ -0,0 +1,13 @@ | |||
1 | // Copyright 2018 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 | // +build appengine | ||
6 | |||
7 | package internal | ||
8 | |||
9 | import "google.golang.org/appengine/urlfetch" | ||
10 | |||
11 | func init() { | ||
12 | appengineClientHook = urlfetch.Client | ||
13 | } | ||
diff --git a/vendor/golang.org/x/oauth2/internal/doc.go b/vendor/golang.org/x/oauth2/internal/doc.go new file mode 100644 index 0000000..03265e8 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/doc.go | |||
@@ -0,0 +1,6 @@ | |||
1 | // Copyright 2017 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 internal contains support packages for oauth2 package. | ||
6 | package internal | ||
diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go new file mode 100644 index 0000000..c0ab196 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/oauth2.go | |||
@@ -0,0 +1,37 @@ | |||
1 | // Copyright 2014 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 internal | ||
6 | |||
7 | import ( | ||
8 | "crypto/rsa" | ||
9 | "crypto/x509" | ||
10 | "encoding/pem" | ||
11 | "errors" | ||
12 | "fmt" | ||
13 | ) | ||
14 | |||
15 | // ParseKey converts the binary contents of a private key file | ||
16 | // to an *rsa.PrivateKey. It detects whether the private key is in a | ||
17 | // PEM container or not. If so, it extracts the the private key | ||
18 | // from PEM container before conversion. It only supports PEM | ||
19 | // containers with no passphrase. | ||
20 | func ParseKey(key []byte) (*rsa.PrivateKey, error) { | ||
21 | block, _ := pem.Decode(key) | ||
22 | if block != nil { | ||
23 | key = block.Bytes | ||
24 | } | ||
25 | parsedKey, err := x509.ParsePKCS8PrivateKey(key) | ||
26 | if err != nil { | ||
27 | parsedKey, err = x509.ParsePKCS1PrivateKey(key) | ||
28 | if err != nil { | ||
29 | return nil, fmt.Errorf("private key should be a PEM or plain PKCS1 or PKCS8; parse error: %v", err) | ||
30 | } | ||
31 | } | ||
32 | parsed, ok := parsedKey.(*rsa.PrivateKey) | ||
33 | if !ok { | ||
34 | return nil, errors.New("private key is invalid") | ||
35 | } | ||
36 | return parsed, nil | ||
37 | } | ||
diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go new file mode 100644 index 0000000..955d5a0 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/token.go | |||
@@ -0,0 +1,300 @@ | |||
1 | // Copyright 2014 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 internal | ||
6 | |||
7 | import ( | ||
8 | "context" | ||
9 | "encoding/json" | ||
10 | "errors" | ||
11 | "fmt" | ||
12 | "io" | ||
13 | "io/ioutil" | ||
14 | "mime" | ||
15 | "net/http" | ||
16 | "net/url" | ||
17 | "strconv" | ||
18 | "strings" | ||
19 | "sync" | ||
20 | "time" | ||
21 | |||
22 | "golang.org/x/net/context/ctxhttp" | ||
23 | ) | ||
24 | |||
25 | // Token represents the credentials used to authorize | ||
26 | // the requests to access protected resources on the OAuth 2.0 | ||
27 | // provider's backend. | ||
28 | // | ||
29 | // This type is a mirror of oauth2.Token and exists to break | ||
30 | // an otherwise-circular dependency. Other internal packages | ||
31 | // should convert this Token into an oauth2.Token before use. | ||
32 | type Token struct { | ||
33 | // AccessToken is the token that authorizes and authenticates | ||
34 | // the requests. | ||
35 | AccessToken string | ||
36 | |||
37 | // TokenType is the type of token. | ||
38 | // The Type method returns either this or "Bearer", the default. | ||
39 | TokenType string | ||
40 | |||
41 | // RefreshToken is a token that's used by the application | ||
42 | // (as opposed to the user) to refresh the access token | ||
43 | // if it expires. | ||
44 | RefreshToken string | ||
45 | |||
46 | // Expiry is the optional expiration time of the access token. | ||
47 | // | ||
48 | // If zero, TokenSource implementations will reuse the same | ||
49 | // token forever and RefreshToken or equivalent | ||
50 | // mechanisms for that TokenSource will not be used. | ||
51 | Expiry time.Time | ||
52 | |||
53 | // Raw optionally contains extra metadata from the server | ||
54 | // when updating a token. | ||
55 | Raw interface{} | ||
56 | } | ||
57 | |||
58 | // tokenJSON is the struct representing the HTTP response from OAuth2 | ||
59 | // providers returning a token in JSON form. | ||
60 | type tokenJSON struct { | ||
61 | AccessToken string `json:"access_token"` | ||
62 | TokenType string `json:"token_type"` | ||
63 | RefreshToken string `json:"refresh_token"` | ||
64 | ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number | ||
65 | Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in | ||
66 | } | ||
67 | |||
68 | func (e *tokenJSON) expiry() (t time.Time) { | ||
69 | if v := e.ExpiresIn; v != 0 { | ||
70 | return time.Now().Add(time.Duration(v) * time.Second) | ||
71 | } | ||
72 | if v := e.Expires; v != 0 { | ||
73 | return time.Now().Add(time.Duration(v) * time.Second) | ||
74 | } | ||
75 | return | ||
76 | } | ||
77 | |||
78 | type expirationTime int32 | ||
79 | |||
80 | func (e *expirationTime) UnmarshalJSON(b []byte) error { | ||
81 | if len(b) == 0 || string(b) == "null" { | ||
82 | return nil | ||
83 | } | ||
84 | var n json.Number | ||
85 | err := json.Unmarshal(b, &n) | ||
86 | if err != nil { | ||
87 | return err | ||
88 | } | ||
89 | i, err := n.Int64() | ||
90 | if err != nil { | ||
91 | return err | ||
92 | } | ||
93 | *e = expirationTime(i) | ||
94 | return nil | ||
95 | } | ||
96 | |||
97 | // RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. | ||
98 | // | ||
99 | // Deprecated: this function no longer does anything. Caller code that | ||
100 | // wants to avoid potential extra HTTP requests made during | ||
101 | // auto-probing of the provider's auth style should set | ||
102 | // Endpoint.AuthStyle. | ||
103 | func RegisterBrokenAuthHeaderProvider(tokenURL string) {} | ||
104 | |||
105 | // AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type. | ||
106 | type AuthStyle int | ||
107 | |||
108 | const ( | ||
109 | AuthStyleUnknown AuthStyle = 0 | ||
110 | AuthStyleInParams AuthStyle = 1 | ||
111 | AuthStyleInHeader AuthStyle = 2 | ||
112 | ) | ||
113 | |||
114 | // authStyleCache is the set of tokenURLs we've successfully used via | ||
115 | // RetrieveToken and which style auth we ended up using. | ||
116 | // It's called a cache, but it doesn't (yet?) shrink. It's expected that | ||
117 | // the set of OAuth2 servers a program contacts over time is fixed and | ||
118 | // small. | ||
119 | var authStyleCache struct { | ||
120 | sync.Mutex | ||
121 | m map[string]AuthStyle // keyed by tokenURL | ||
122 | } | ||
123 | |||
124 | // ResetAuthCache resets the global authentication style cache used | ||
125 | // for AuthStyleUnknown token requests. | ||
126 | func ResetAuthCache() { | ||
127 | authStyleCache.Lock() | ||
128 | defer authStyleCache.Unlock() | ||
129 | authStyleCache.m = nil | ||
130 | } | ||
131 | |||
132 | // lookupAuthStyle reports which auth style we last used with tokenURL | ||
133 | // when calling RetrieveToken and whether we have ever done so. | ||
134 | func lookupAuthStyle(tokenURL string) (style AuthStyle, ok bool) { | ||
135 | authStyleCache.Lock() | ||
136 | defer authStyleCache.Unlock() | ||
137 | style, ok = authStyleCache.m[tokenURL] | ||
138 | return | ||
139 | } | ||
140 | |||
141 | // setAuthStyle adds an entry to authStyleCache, documented above. | ||
142 | func setAuthStyle(tokenURL string, v AuthStyle) { | ||
143 | authStyleCache.Lock() | ||
144 | defer authStyleCache.Unlock() | ||
145 | if authStyleCache.m == nil { | ||
146 | authStyleCache.m = make(map[string]AuthStyle) | ||
147 | } | ||
148 | authStyleCache.m[tokenURL] = v | ||
149 | } | ||
150 | |||
151 | // newTokenRequest returns a new *http.Request to retrieve a new token | ||
152 | // from tokenURL using the provided clientID, clientSecret, and POST | ||
153 | // body parameters. | ||
154 | // | ||
155 | // inParams is whether the clientID & clientSecret should be encoded | ||
156 | // as the POST body. An 'inParams' value of true means to send it in | ||
157 | // the POST body (along with any values in v); false means to send it | ||
158 | // in the Authorization header. | ||
159 | func newTokenRequest(tokenURL, clientID, clientSecret string, v url.Values, authStyle AuthStyle) (*http.Request, error) { | ||
160 | if authStyle == AuthStyleInParams { | ||
161 | v = cloneURLValues(v) | ||
162 | if clientID != "" { | ||
163 | v.Set("client_id", clientID) | ||
164 | } | ||
165 | if clientSecret != "" { | ||
166 | v.Set("client_secret", clientSecret) | ||
167 | } | ||
168 | } | ||
169 | req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode())) | ||
170 | if err != nil { | ||
171 | return nil, err | ||
172 | } | ||
173 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded") | ||
174 | if authStyle == AuthStyleInHeader { | ||
175 | req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret)) | ||
176 | } | ||
177 | return req, nil | ||
178 | } | ||
179 | |||
180 | func cloneURLValues(v url.Values) url.Values { | ||
181 | v2 := make(url.Values, len(v)) | ||
182 | for k, vv := range v { | ||
183 | v2[k] = append([]string(nil), vv...) | ||
184 | } | ||
185 | return v2 | ||
186 | } | ||
187 | |||
188 | func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle) (*Token, error) { | ||
189 | needsAuthStyleProbe := authStyle == 0 | ||
190 | if needsAuthStyleProbe { | ||
191 | if style, ok := lookupAuthStyle(tokenURL); ok { | ||
192 | authStyle = style | ||
193 | needsAuthStyleProbe = false | ||
194 | } else { | ||
195 | authStyle = AuthStyleInHeader // the first way we'll try | ||
196 | } | ||
197 | } | ||
198 | req, err := newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) | ||
199 | if err != nil { | ||
200 | return nil, err | ||
201 | } | ||
202 | token, err := doTokenRoundTrip(ctx, req) | ||
203 | if err != nil && needsAuthStyleProbe { | ||
204 | // If we get an error, assume the server wants the | ||
205 | // clientID & clientSecret in a different form. | ||
206 | // See https://code.google.com/p/goauth2/issues/detail?id=31 for background. | ||
207 | // In summary: | ||
208 | // - Reddit only accepts client secret in the Authorization header | ||
209 | // - Dropbox accepts either it in URL param or Auth header, but not both. | ||
210 | // - Google only accepts URL param (not spec compliant?), not Auth header | ||
211 | // - Stripe only accepts client secret in Auth header with Bearer method, not Basic | ||
212 | // | ||
213 | // We used to maintain a big table in this code of all the sites and which way | ||
214 | // they went, but maintaining it didn't scale & got annoying. | ||
215 | // So just try both ways. | ||
216 | authStyle = AuthStyleInParams // the second way we'll try | ||
217 | req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) | ||
218 | token, err = doTokenRoundTrip(ctx, req) | ||
219 | } | ||
220 | if needsAuthStyleProbe && err == nil { | ||
221 | setAuthStyle(tokenURL, authStyle) | ||
222 | } | ||
223 | // Don't overwrite `RefreshToken` with an empty value | ||
224 | // if this was a token refreshing request. | ||
225 | if token != nil && token.RefreshToken == "" { | ||
226 | token.RefreshToken = v.Get("refresh_token") | ||
227 | } | ||
228 | return token, err | ||
229 | } | ||
230 | |||
231 | func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { | ||
232 | r, err := ctxhttp.Do(ctx, ContextClient(ctx), req) | ||
233 | if err != nil { | ||
234 | return nil, err | ||
235 | } | ||
236 | body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20)) | ||
237 | r.Body.Close() | ||
238 | if err != nil { | ||
239 | return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) | ||
240 | } | ||
241 | if code := r.StatusCode; code < 200 || code > 299 { | ||
242 | return nil, &RetrieveError{ | ||
243 | Response: r, | ||
244 | Body: body, | ||
245 | } | ||
246 | } | ||
247 | |||
248 | var token *Token | ||
249 | content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) | ||
250 | switch content { | ||
251 | case "application/x-www-form-urlencoded", "text/plain": | ||
252 | vals, err := url.ParseQuery(string(body)) | ||
253 | if err != nil { | ||
254 | return nil, err | ||
255 | } | ||
256 | token = &Token{ | ||
257 | AccessToken: vals.Get("access_token"), | ||
258 | TokenType: vals.Get("token_type"), | ||
259 | RefreshToken: vals.Get("refresh_token"), | ||
260 | Raw: vals, | ||
261 | } | ||
262 | e := vals.Get("expires_in") | ||
263 | if e == "" || e == "null" { | ||
264 | // TODO(jbd): Facebook's OAuth2 implementation is broken and | ||
265 | // returns expires_in field in expires. Remove the fallback to expires, | ||
266 | // when Facebook fixes their implementation. | ||
267 | e = vals.Get("expires") | ||
268 | } | ||
269 | expires, _ := strconv.Atoi(e) | ||
270 | if expires != 0 { | ||
271 | token.Expiry = time.Now().Add(time.Duration(expires) * time.Second) | ||
272 | } | ||
273 | default: | ||
274 | var tj tokenJSON | ||
275 | if err = json.Unmarshal(body, &tj); err != nil { | ||
276 | return nil, err | ||
277 | } | ||
278 | token = &Token{ | ||
279 | AccessToken: tj.AccessToken, | ||
280 | TokenType: tj.TokenType, | ||
281 | RefreshToken: tj.RefreshToken, | ||
282 | Expiry: tj.expiry(), | ||
283 | Raw: make(map[string]interface{}), | ||
284 | } | ||
285 | json.Unmarshal(body, &token.Raw) // no error checks for optional fields | ||
286 | } | ||
287 | if token.AccessToken == "" { | ||
288 | return nil, errors.New("oauth2: server response missing access_token") | ||
289 | } | ||
290 | return token, nil | ||
291 | } | ||
292 | |||
293 | type RetrieveError struct { | ||
294 | Response *http.Response | ||
295 | Body []byte | ||
296 | } | ||
297 | |||
298 | func (r *RetrieveError) Error() string { | ||
299 | return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) | ||
300 | } | ||
diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go new file mode 100644 index 0000000..572074a --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/transport.go | |||
@@ -0,0 +1,33 @@ | |||
1 | // Copyright 2014 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 internal | ||
6 | |||
7 | import ( | ||
8 | "context" | ||
9 | "net/http" | ||
10 | ) | ||
11 | |||
12 | // HTTPClient is the context key to use with golang.org/x/net/context's | ||
13 | // WithValue function to associate an *http.Client value with a context. | ||
14 | var HTTPClient ContextKey | ||
15 | |||
16 | // ContextKey is just an empty struct. It exists so HTTPClient can be | ||
17 | // an immutable public variable with a unique type. It's immutable | ||
18 | // because nobody else can create a ContextKey, being unexported. | ||
19 | type ContextKey struct{} | ||
20 | |||
21 | var appengineClientHook func(context.Context) *http.Client | ||
22 | |||
23 | func ContextClient(ctx context.Context) *http.Client { | ||
24 | if ctx != nil { | ||
25 | if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { | ||
26 | return hc | ||
27 | } | ||
28 | } | ||
29 | if appengineClientHook != nil { | ||
30 | return appengineClientHook(ctx) | ||
31 | } | ||
32 | return http.DefaultClient | ||
33 | } | ||
diff --git a/vendor/golang.org/x/oauth2/jws/jws.go b/vendor/golang.org/x/oauth2/jws/jws.go new file mode 100644 index 0000000..683d2d2 --- /dev/null +++ b/vendor/golang.org/x/oauth2/jws/jws.go | |||
@@ -0,0 +1,182 @@ | |||
1 | // Copyright 2014 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 jws provides a partial implementation | ||
6 | // of JSON Web Signature encoding and decoding. | ||
7 | // It exists to support the golang.org/x/oauth2 package. | ||
8 | // | ||
9 | // See RFC 7515. | ||
10 | // | ||
11 | // Deprecated: this package is not intended for public use and might be | ||
12 | // removed in the future. It exists for internal use only. | ||
13 | // Please switch to another JWS package or copy this package into your own | ||
14 | // source tree. | ||
15 | package jws // import "golang.org/x/oauth2/jws" | ||
16 | |||
17 | import ( | ||
18 | "bytes" | ||
19 | "crypto" | ||
20 | "crypto/rand" | ||
21 | "crypto/rsa" | ||
22 | "crypto/sha256" | ||
23 | "encoding/base64" | ||
24 | "encoding/json" | ||
25 | "errors" | ||
26 | "fmt" | ||
27 | "strings" | ||
28 | "time" | ||
29 | ) | ||
30 | |||
31 | // ClaimSet contains information about the JWT signature including the | ||
32 | // permissions being requested (scopes), the target of the token, the issuer, | ||
33 | // the time the token was issued, and the lifetime of the token. | ||
34 | type ClaimSet struct { | ||
35 | Iss string `json:"iss"` // email address of the client_id of the application making the access token request | ||
36 | Scope string `json:"scope,omitempty"` // space-delimited list of the permissions the application requests | ||
37 | Aud string `json:"aud"` // descriptor of the intended target of the assertion (Optional). | ||
38 | Exp int64 `json:"exp"` // the expiration time of the assertion (seconds since Unix epoch) | ||
39 | Iat int64 `json:"iat"` // the time the assertion was issued (seconds since Unix epoch) | ||
40 | Typ string `json:"typ,omitempty"` // token type (Optional). | ||
41 | |||
42 | // Email for which the application is requesting delegated access (Optional). | ||
43 | Sub string `json:"sub,omitempty"` | ||
44 | |||
45 | // The old name of Sub. Client keeps setting Prn to be | ||
46 | // complaint with legacy OAuth 2.0 providers. (Optional) | ||
47 | Prn string `json:"prn,omitempty"` | ||
48 | |||
49 | // See http://tools.ietf.org/html/draft-jones-json-web-token-10#section-4.3 | ||
50 | // This array is marshalled using custom code (see (c *ClaimSet) encode()). | ||
51 | PrivateClaims map[string]interface{} `json:"-"` | ||
52 | } | ||
53 | |||
54 | func (c *ClaimSet) encode() (string, error) { | ||
55 | // Reverting time back for machines whose time is not perfectly in sync. | ||
56 | // If client machine's time is in the future according | ||
57 | // to Google servers, an access token will not be issued. | ||
58 | now := time.Now().Add(-10 * time.Second) | ||
59 | if c.Iat == 0 { | ||
60 | c.Iat = now.Unix() | ||
61 | } | ||
62 | if c.Exp == 0 { | ||
63 | c.Exp = now.Add(time.Hour).Unix() | ||
64 | } | ||
65 | if c.Exp < c.Iat { | ||
66 | return "", fmt.Errorf("jws: invalid Exp = %v; must be later than Iat = %v", c.Exp, c.Iat) | ||
67 | } | ||
68 | |||
69 | b, err := json.Marshal(c) | ||
70 | if err != nil { | ||
71 | return "", err | ||
72 | } | ||
73 | |||
74 | if len(c.PrivateClaims) == 0 { | ||
75 | return base64.RawURLEncoding.EncodeToString(b), nil | ||
76 | } | ||
77 | |||
78 | // Marshal private claim set and then append it to b. | ||
79 | prv, err := json.Marshal(c.PrivateClaims) | ||
80 | if err != nil { | ||
81 | return "", fmt.Errorf("jws: invalid map of private claims %v", c.PrivateClaims) | ||
82 | } | ||
83 | |||
84 | // Concatenate public and private claim JSON objects. | ||
85 | if !bytes.HasSuffix(b, []byte{'}'}) { | ||
86 | return "", fmt.Errorf("jws: invalid JSON %s", b) | ||
87 | } | ||
88 | if !bytes.HasPrefix(prv, []byte{'{'}) { | ||
89 | return "", fmt.Errorf("jws: invalid JSON %s", prv) | ||
90 | } | ||
91 | b[len(b)-1] = ',' // Replace closing curly brace with a comma. | ||
92 | b = append(b, prv[1:]...) // Append private claims. | ||
93 | return base64.RawURLEncoding.EncodeToString(b), nil | ||
94 | } | ||
95 | |||
96 | // Header represents the header for the signed JWS payloads. | ||
97 | type Header struct { | ||
98 | // The algorithm used for signature. | ||
99 | Algorithm string `json:"alg"` | ||
100 | |||
101 | // Represents the token type. | ||
102 | Typ string `json:"typ"` | ||
103 | |||
104 | // The optional hint of which key is being used. | ||
105 | KeyID string `json:"kid,omitempty"` | ||
106 | } | ||
107 | |||
108 | func (h *Header) encode() (string, error) { | ||
109 | b, err := json.Marshal(h) | ||
110 | if err != nil { | ||
111 | return "", err | ||
112 | } | ||
113 | return base64.RawURLEncoding.EncodeToString(b), nil | ||
114 | } | ||
115 | |||
116 | // Decode decodes a claim set from a JWS payload. | ||
117 | func Decode(payload string) (*ClaimSet, error) { | ||
118 | // decode returned id token to get expiry | ||
119 | s := strings.Split(payload, ".") | ||
120 | if len(s) < 2 { | ||
121 | // TODO(jbd): Provide more context about the error. | ||
122 | return nil, errors.New("jws: invalid token received") | ||
123 | } | ||
124 | decoded, err := base64.RawURLEncoding.DecodeString(s[1]) | ||
125 | if err != nil { | ||
126 | return nil, err | ||
127 | } | ||
128 | c := &ClaimSet{} | ||
129 | err = json.NewDecoder(bytes.NewBuffer(decoded)).Decode(c) | ||
130 | return c, err | ||
131 | } | ||
132 | |||
133 | // Signer returns a signature for the given data. | ||
134 | type Signer func(data []byte) (sig []byte, err error) | ||
135 | |||
136 | // EncodeWithSigner encodes a header and claim set with the provided signer. | ||
137 | func EncodeWithSigner(header *Header, c *ClaimSet, sg Signer) (string, error) { | ||
138 | head, err := header.encode() | ||
139 | if err != nil { | ||
140 | return "", err | ||
141 | } | ||
142 | cs, err := c.encode() | ||
143 | if err != nil { | ||
144 | return "", err | ||
145 | } | ||
146 | ss := fmt.Sprintf("%s.%s", head, cs) | ||
147 | sig, err := sg([]byte(ss)) | ||
148 | if err != nil { | ||
149 | return "", err | ||
150 | } | ||
151 | return fmt.Sprintf("%s.%s", ss, base64.RawURLEncoding.EncodeToString(sig)), nil | ||
152 | } | ||
153 | |||
154 | // Encode encodes a signed JWS with provided header and claim set. | ||
155 | // This invokes EncodeWithSigner using crypto/rsa.SignPKCS1v15 with the given RSA private key. | ||
156 | func Encode(header *Header, c *ClaimSet, key *rsa.PrivateKey) (string, error) { | ||
157 | sg := func(data []byte) (sig []byte, err error) { | ||
158 | h := sha256.New() | ||
159 | h.Write(data) | ||
160 | return rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, h.Sum(nil)) | ||
161 | } | ||
162 | return EncodeWithSigner(header, c, sg) | ||
163 | } | ||
164 | |||
165 | // Verify tests whether the provided JWT token's signature was produced by the private key | ||
166 | // associated with the supplied public key. | ||
167 | func Verify(token string, key *rsa.PublicKey) error { | ||
168 | parts := strings.Split(token, ".") | ||
169 | if len(parts) != 3 { | ||
170 | return errors.New("jws: invalid token received, token must have 3 parts") | ||
171 | } | ||
172 | |||
173 | signedContent := parts[0] + "." + parts[1] | ||
174 | signatureString, err := base64.RawURLEncoding.DecodeString(parts[2]) | ||
175 | if err != nil { | ||
176 | return err | ||
177 | } | ||
178 | |||
179 | h := sha256.New() | ||
180 | h.Write([]byte(signedContent)) | ||
181 | return rsa.VerifyPKCS1v15(key, crypto.SHA256, h.Sum(nil), []byte(signatureString)) | ||
182 | } | ||
diff --git a/vendor/golang.org/x/oauth2/jwt/jwt.go b/vendor/golang.org/x/oauth2/jwt/jwt.go new file mode 100644 index 0000000..99f3e0a --- /dev/null +++ b/vendor/golang.org/x/oauth2/jwt/jwt.go | |||
@@ -0,0 +1,170 @@ | |||
1 | // Copyright 2014 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 jwt implements the OAuth 2.0 JSON Web Token flow, commonly | ||
6 | // known as "two-legged OAuth 2.0". | ||
7 | // | ||
8 | // See: https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12 | ||
9 | package jwt | ||
10 | |||
11 | import ( | ||
12 | "context" | ||
13 | "encoding/json" | ||
14 | "fmt" | ||
15 | "io" | ||
16 | "io/ioutil" | ||
17 | "net/http" | ||
18 | "net/url" | ||
19 | "strings" | ||
20 | "time" | ||
21 | |||
22 | "golang.org/x/oauth2" | ||
23 | "golang.org/x/oauth2/internal" | ||
24 | "golang.org/x/oauth2/jws" | ||
25 | ) | ||
26 | |||
27 | var ( | ||
28 | defaultGrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer" | ||
29 | defaultHeader = &jws.Header{Algorithm: "RS256", Typ: "JWT"} | ||
30 | ) | ||
31 | |||
32 | // Config is the configuration for using JWT to fetch tokens, | ||
33 | // commonly known as "two-legged OAuth 2.0". | ||
34 | type Config struct { | ||
35 | // Email is the OAuth client identifier used when communicating with | ||
36 | // the configured OAuth provider. | ||
37 | Email string | ||
38 | |||
39 | // PrivateKey contains the contents of an RSA private key or the | ||
40 | // contents of a PEM file that contains a private key. The provided | ||
41 | // private key is used to sign JWT payloads. | ||
42 | // PEM containers with a passphrase are not supported. | ||
43 | // Use the following command to convert a PKCS 12 file into a PEM. | ||
44 | // | ||
45 | // $ openssl pkcs12 -in key.p12 -out key.pem -nodes | ||
46 | // | ||
47 | PrivateKey []byte | ||
48 | |||
49 | // PrivateKeyID contains an optional hint indicating which key is being | ||
50 | // used. | ||
51 | PrivateKeyID string | ||
52 | |||
53 | // Subject is the optional user to impersonate. | ||
54 | Subject string | ||
55 | |||
56 | // Scopes optionally specifies a list of requested permission scopes. | ||
57 | Scopes []string | ||
58 | |||
59 | // TokenURL is the endpoint required to complete the 2-legged JWT flow. | ||
60 | TokenURL string | ||
61 | |||
62 | // Expires optionally specifies how long the token is valid for. | ||
63 | Expires time.Duration | ||
64 | |||
65 | // Audience optionally specifies the intended audience of the | ||
66 | // request. If empty, the value of TokenURL is used as the | ||
67 | // intended audience. | ||
68 | Audience string | ||
69 | } | ||
70 | |||
71 | // TokenSource returns a JWT TokenSource using the configuration | ||
72 | // in c and the HTTP client from the provided context. | ||
73 | func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource { | ||
74 | return oauth2.ReuseTokenSource(nil, jwtSource{ctx, c}) | ||
75 | } | ||
76 | |||
77 | // Client returns an HTTP client wrapping the context's | ||
78 | // HTTP transport and adding Authorization headers with tokens | ||
79 | // obtained from c. | ||
80 | // | ||
81 | // The returned client and its Transport should not be modified. | ||
82 | func (c *Config) Client(ctx context.Context) *http.Client { | ||
83 | return oauth2.NewClient(ctx, c.TokenSource(ctx)) | ||
84 | } | ||
85 | |||
86 | // jwtSource is a source that always does a signed JWT request for a token. | ||
87 | // It should typically be wrapped with a reuseTokenSource. | ||
88 | type jwtSource struct { | ||
89 | ctx context.Context | ||
90 | conf *Config | ||
91 | } | ||
92 | |||
93 | func (js jwtSource) Token() (*oauth2.Token, error) { | ||
94 | pk, err := internal.ParseKey(js.conf.PrivateKey) | ||
95 | if err != nil { | ||
96 | return nil, err | ||
97 | } | ||
98 | hc := oauth2.NewClient(js.ctx, nil) | ||
99 | claimSet := &jws.ClaimSet{ | ||
100 | Iss: js.conf.Email, | ||
101 | Scope: strings.Join(js.conf.Scopes, " "), | ||
102 | Aud: js.conf.TokenURL, | ||
103 | } | ||
104 | if subject := js.conf.Subject; subject != "" { | ||
105 | claimSet.Sub = subject | ||
106 | // prn is the old name of sub. Keep setting it | ||
107 | // to be compatible with legacy OAuth 2.0 providers. | ||
108 | claimSet.Prn = subject | ||
109 | } | ||
110 | if t := js.conf.Expires; t > 0 { | ||
111 | claimSet.Exp = time.Now().Add(t).Unix() | ||
112 | } | ||
113 | if aud := js.conf.Audience; aud != "" { | ||
114 | claimSet.Aud = aud | ||
115 | } | ||
116 | h := *defaultHeader | ||
117 | h.KeyID = js.conf.PrivateKeyID | ||
118 | payload, err := jws.Encode(&h, claimSet, pk) | ||
119 | if err != nil { | ||
120 | return nil, err | ||
121 | } | ||
122 | v := url.Values{} | ||
123 | v.Set("grant_type", defaultGrantType) | ||
124 | v.Set("assertion", payload) | ||
125 | resp, err := hc.PostForm(js.conf.TokenURL, v) | ||
126 | if err != nil { | ||
127 | return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) | ||
128 | } | ||
129 | defer resp.Body.Close() | ||
130 | body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20)) | ||
131 | if err != nil { | ||
132 | return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) | ||
133 | } | ||
134 | if c := resp.StatusCode; c < 200 || c > 299 { | ||
135 | return nil, &oauth2.RetrieveError{ | ||
136 | Response: resp, | ||
137 | Body: body, | ||
138 | } | ||
139 | } | ||
140 | // tokenRes is the JSON response body. | ||
141 | var tokenRes struct { | ||
142 | AccessToken string `json:"access_token"` | ||
143 | TokenType string `json:"token_type"` | ||
144 | IDToken string `json:"id_token"` | ||
145 | ExpiresIn int64 `json:"expires_in"` // relative seconds from now | ||
146 | } | ||
147 | if err := json.Unmarshal(body, &tokenRes); err != nil { | ||
148 | return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) | ||
149 | } | ||
150 | token := &oauth2.Token{ | ||
151 | AccessToken: tokenRes.AccessToken, | ||
152 | TokenType: tokenRes.TokenType, | ||
153 | } | ||
154 | raw := make(map[string]interface{}) | ||
155 | json.Unmarshal(body, &raw) // no error checks for optional fields | ||
156 | token = token.WithExtra(raw) | ||
157 | |||
158 | if secs := tokenRes.ExpiresIn; secs > 0 { | ||
159 | token.Expiry = time.Now().Add(time.Duration(secs) * time.Second) | ||
160 | } | ||
161 | if v := tokenRes.IDToken; v != "" { | ||
162 | // decode returned id token to get expiry | ||
163 | claimSet, err := jws.Decode(v) | ||
164 | if err != nil { | ||
165 | return nil, fmt.Errorf("oauth2: error decoding JWT token: %v", err) | ||
166 | } | ||
167 | token.Expiry = time.Unix(claimSet.Exp, 0) | ||
168 | } | ||
169 | return token, nil | ||
170 | } | ||
diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go new file mode 100644 index 0000000..428283f --- /dev/null +++ b/vendor/golang.org/x/oauth2/oauth2.go | |||
@@ -0,0 +1,381 @@ | |||
1 | // Copyright 2014 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 oauth2 provides support for making | ||
6 | // OAuth2 authorized and authenticated HTTP requests, | ||
7 | // as specified in RFC 6749. | ||
8 | // It can additionally grant authorization with Bearer JWT. | ||
9 | package oauth2 // import "golang.org/x/oauth2" | ||
10 | |||
11 | import ( | ||
12 | "bytes" | ||
13 | "context" | ||
14 | "errors" | ||
15 | "net/http" | ||
16 | "net/url" | ||
17 | "strings" | ||
18 | "sync" | ||
19 | |||
20 | "golang.org/x/oauth2/internal" | ||
21 | ) | ||
22 | |||
23 | // NoContext is the default context you should supply if not using | ||
24 | // your own context.Context (see https://golang.org/x/net/context). | ||
25 | // | ||
26 | // Deprecated: Use context.Background() or context.TODO() instead. | ||
27 | var NoContext = context.TODO() | ||
28 | |||
29 | // RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. | ||
30 | // | ||
31 | // Deprecated: this function no longer does anything. Caller code that | ||
32 | // wants to avoid potential extra HTTP requests made during | ||
33 | // auto-probing of the provider's auth style should set | ||
34 | // Endpoint.AuthStyle. | ||
35 | func RegisterBrokenAuthHeaderProvider(tokenURL string) {} | ||
36 | |||
37 | // Config describes a typical 3-legged OAuth2 flow, with both the | ||
38 | // client application information and the server's endpoint URLs. | ||
39 | // For the client credentials 2-legged OAuth2 flow, see the clientcredentials | ||
40 | // package (https://golang.org/x/oauth2/clientcredentials). | ||
41 | type Config struct { | ||
42 | // ClientID is the application's ID. | ||
43 | ClientID string | ||
44 | |||
45 | // ClientSecret is the application's secret. | ||
46 | ClientSecret string | ||
47 | |||
48 | // Endpoint contains the resource server's token endpoint | ||
49 | // URLs. These are constants specific to each server and are | ||
50 | // often available via site-specific packages, such as | ||
51 | // google.Endpoint or github.Endpoint. | ||
52 | Endpoint Endpoint | ||
53 | |||
54 | // RedirectURL is the URL to redirect users going through | ||
55 | // the OAuth flow, after the resource owner's URLs. | ||
56 | RedirectURL string | ||
57 | |||
58 | // Scope specifies optional requested permissions. | ||
59 | Scopes []string | ||
60 | } | ||
61 | |||
62 | // A TokenSource is anything that can return a token. | ||
63 | type TokenSource interface { | ||
64 | // Token returns a token or an error. | ||
65 | // Token must be safe for concurrent use by multiple goroutines. | ||
66 | // The returned Token must not be modified. | ||
67 | Token() (*Token, error) | ||
68 | } | ||
69 | |||
70 | // Endpoint represents an OAuth 2.0 provider's authorization and token | ||
71 | // endpoint URLs. | ||
72 | type Endpoint struct { | ||
73 | AuthURL string | ||
74 | TokenURL string | ||
75 | |||
76 | // AuthStyle optionally specifies how the endpoint wants the | ||
77 | // client ID & client secret sent. The zero value means to | ||
78 | // auto-detect. | ||
79 | AuthStyle AuthStyle | ||
80 | } | ||
81 | |||
82 | // AuthStyle represents how requests for tokens are authenticated | ||
83 | // to the server. | ||
84 | type AuthStyle int | ||
85 | |||
86 | const ( | ||
87 | // AuthStyleAutoDetect means to auto-detect which authentication | ||
88 | // style the provider wants by trying both ways and caching | ||
89 | // the successful way for the future. | ||
90 | AuthStyleAutoDetect AuthStyle = 0 | ||
91 | |||
92 | // AuthStyleInParams sends the "client_id" and "client_secret" | ||
93 | // in the POST body as application/x-www-form-urlencoded parameters. | ||
94 | AuthStyleInParams AuthStyle = 1 | ||
95 | |||
96 | // AuthStyleInHeader sends the client_id and client_password | ||
97 | // using HTTP Basic Authorization. This is an optional style | ||
98 | // described in the OAuth2 RFC 6749 section 2.3.1. | ||
99 | AuthStyleInHeader AuthStyle = 2 | ||
100 | ) | ||
101 | |||
102 | var ( | ||
103 | // AccessTypeOnline and AccessTypeOffline are options passed | ||
104 | // to the Options.AuthCodeURL method. They modify the | ||
105 | // "access_type" field that gets sent in the URL returned by | ||
106 | // AuthCodeURL. | ||
107 | // | ||
108 | // Online is the default if neither is specified. If your | ||
109 | // application needs to refresh access tokens when the user | ||
110 | // is not present at the browser, then use offline. This will | ||
111 | // result in your application obtaining a refresh token the | ||
112 | // first time your application exchanges an authorization | ||
113 | // code for a user. | ||
114 | AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online") | ||
115 | AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline") | ||
116 | |||
117 | // ApprovalForce forces the users to view the consent dialog | ||
118 | // and confirm the permissions request at the URL returned | ||
119 | // from AuthCodeURL, even if they've already done so. | ||
120 | ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force") | ||
121 | ) | ||
122 | |||
123 | // An AuthCodeOption is passed to Config.AuthCodeURL. | ||
124 | type AuthCodeOption interface { | ||
125 | setValue(url.Values) | ||
126 | } | ||
127 | |||
128 | type setParam struct{ k, v string } | ||
129 | |||
130 | func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) } | ||
131 | |||
132 | // SetAuthURLParam builds an AuthCodeOption which passes key/value parameters | ||
133 | // to a provider's authorization endpoint. | ||
134 | func SetAuthURLParam(key, value string) AuthCodeOption { | ||
135 | return setParam{key, value} | ||
136 | } | ||
137 | |||
138 | // AuthCodeURL returns a URL to OAuth 2.0 provider's consent page | ||
139 | // that asks for permissions for the required scopes explicitly. | ||
140 | // | ||
141 | // State is a token to protect the user from CSRF attacks. You must | ||
142 | // always provide a non-empty string and validate that it matches the | ||
143 | // the state query parameter on your redirect callback. | ||
144 | // See http://tools.ietf.org/html/rfc6749#section-10.12 for more info. | ||
145 | // | ||
146 | // Opts may include AccessTypeOnline or AccessTypeOffline, as well | ||
147 | // as ApprovalForce. | ||
148 | // It can also be used to pass the PKCE challenge. | ||
149 | // See https://www.oauth.com/oauth2-servers/pkce/ for more info. | ||
150 | func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { | ||
151 | var buf bytes.Buffer | ||
152 | buf.WriteString(c.Endpoint.AuthURL) | ||
153 | v := url.Values{ | ||
154 | "response_type": {"code"}, | ||
155 | "client_id": {c.ClientID}, | ||
156 | } | ||
157 | if c.RedirectURL != "" { | ||
158 | v.Set("redirect_uri", c.RedirectURL) | ||
159 | } | ||
160 | if len(c.Scopes) > 0 { | ||
161 | v.Set("scope", strings.Join(c.Scopes, " ")) | ||
162 | } | ||
163 | if state != "" { | ||
164 | // TODO(light): Docs say never to omit state; don't allow empty. | ||
165 | v.Set("state", state) | ||
166 | } | ||
167 | for _, opt := range opts { | ||
168 | opt.setValue(v) | ||
169 | } | ||
170 | if strings.Contains(c.Endpoint.AuthURL, "?") { | ||
171 | buf.WriteByte('&') | ||
172 | } else { | ||
173 | buf.WriteByte('?') | ||
174 | } | ||
175 | buf.WriteString(v.Encode()) | ||
176 | return buf.String() | ||
177 | } | ||
178 | |||
179 | // PasswordCredentialsToken converts a resource owner username and password | ||
180 | // pair into a token. | ||
181 | // | ||
182 | // Per the RFC, this grant type should only be used "when there is a high | ||
183 | // degree of trust between the resource owner and the client (e.g., the client | ||
184 | // is part of the device operating system or a highly privileged application), | ||
185 | // and when other authorization grant types are not available." | ||
186 | // See https://tools.ietf.org/html/rfc6749#section-4.3 for more info. | ||
187 | // | ||
188 | // The provided context optionally controls which HTTP client is used. See the HTTPClient variable. | ||
189 | func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { | ||
190 | v := url.Values{ | ||
191 | "grant_type": {"password"}, | ||
192 | "username": {username}, | ||
193 | "password": {password}, | ||
194 | } | ||
195 | if len(c.Scopes) > 0 { | ||
196 | v.Set("scope", strings.Join(c.Scopes, " ")) | ||
197 | } | ||
198 | return retrieveToken(ctx, c, v) | ||
199 | } | ||
200 | |||
201 | // Exchange converts an authorization code into a token. | ||
202 | // | ||
203 | // It is used after a resource provider redirects the user back | ||
204 | // to the Redirect URI (the URL obtained from AuthCodeURL). | ||
205 | // | ||
206 | // The provided context optionally controls which HTTP client is used. See the HTTPClient variable. | ||
207 | // | ||
208 | // The code will be in the *http.Request.FormValue("code"). Before | ||
209 | // calling Exchange, be sure to validate FormValue("state"). | ||
210 | // | ||
211 | // Opts may include the PKCE verifier code if previously used in AuthCodeURL. | ||
212 | // See https://www.oauth.com/oauth2-servers/pkce/ for more info. | ||
213 | func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) { | ||
214 | v := url.Values{ | ||
215 | "grant_type": {"authorization_code"}, | ||
216 | "code": {code}, | ||
217 | } | ||
218 | if c.RedirectURL != "" { | ||
219 | v.Set("redirect_uri", c.RedirectURL) | ||
220 | } | ||
221 | for _, opt := range opts { | ||
222 | opt.setValue(v) | ||
223 | } | ||
224 | return retrieveToken(ctx, c, v) | ||
225 | } | ||
226 | |||
227 | // Client returns an HTTP client using the provided token. | ||
228 | // The token will auto-refresh as necessary. The underlying | ||
229 | // HTTP transport will be obtained using the provided context. | ||
230 | // The returned client and its Transport should not be modified. | ||
231 | func (c *Config) Client(ctx context.Context, t *Token) *http.Client { | ||
232 | return NewClient(ctx, c.TokenSource(ctx, t)) | ||
233 | } | ||
234 | |||
235 | // TokenSource returns a TokenSource that returns t until t expires, | ||
236 | // automatically refreshing it as necessary using the provided context. | ||
237 | // | ||
238 | // Most users will use Config.Client instead. | ||
239 | func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource { | ||
240 | tkr := &tokenRefresher{ | ||
241 | ctx: ctx, | ||
242 | conf: c, | ||
243 | } | ||
244 | if t != nil { | ||
245 | tkr.refreshToken = t.RefreshToken | ||
246 | } | ||
247 | return &reuseTokenSource{ | ||
248 | t: t, | ||
249 | new: tkr, | ||
250 | } | ||
251 | } | ||
252 | |||
253 | // tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token" | ||
254 | // HTTP requests to renew a token using a RefreshToken. | ||
255 | type tokenRefresher struct { | ||
256 | ctx context.Context // used to get HTTP requests | ||
257 | conf *Config | ||
258 | refreshToken string | ||
259 | } | ||
260 | |||
261 | // WARNING: Token is not safe for concurrent access, as it | ||
262 | // updates the tokenRefresher's refreshToken field. | ||
263 | // Within this package, it is used by reuseTokenSource which | ||
264 | // synchronizes calls to this method with its own mutex. | ||
265 | func (tf *tokenRefresher) Token() (*Token, error) { | ||
266 | if tf.refreshToken == "" { | ||
267 | return nil, errors.New("oauth2: token expired and refresh token is not set") | ||
268 | } | ||
269 | |||
270 | tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{ | ||
271 | "grant_type": {"refresh_token"}, | ||
272 | "refresh_token": {tf.refreshToken}, | ||
273 | }) | ||
274 | |||
275 | if err != nil { | ||
276 | return nil, err | ||
277 | } | ||
278 | if tf.refreshToken != tk.RefreshToken { | ||
279 | tf.refreshToken = tk.RefreshToken | ||
280 | } | ||
281 | return tk, err | ||
282 | } | ||
283 | |||
284 | // reuseTokenSource is a TokenSource that holds a single token in memory | ||
285 | // and validates its expiry before each call to retrieve it with | ||
286 | // Token. If it's expired, it will be auto-refreshed using the | ||
287 | // new TokenSource. | ||
288 | type reuseTokenSource struct { | ||
289 | new TokenSource // called when t is expired. | ||
290 | |||
291 | mu sync.Mutex // guards t | ||
292 | t *Token | ||
293 | } | ||
294 | |||
295 | // Token returns the current token if it's still valid, else will | ||
296 | // refresh the current token (using r.Context for HTTP client | ||
297 | // information) and return the new one. | ||
298 | func (s *reuseTokenSource) Token() (*Token, error) { | ||
299 | s.mu.Lock() | ||
300 | defer s.mu.Unlock() | ||
301 | if s.t.Valid() { | ||
302 | return s.t, nil | ||
303 | } | ||
304 | t, err := s.new.Token() | ||
305 | if err != nil { | ||
306 | return nil, err | ||
307 | } | ||
308 | s.t = t | ||
309 | return t, nil | ||
310 | } | ||
311 | |||
312 | // StaticTokenSource returns a TokenSource that always returns the same token. | ||
313 | // Because the provided token t is never refreshed, StaticTokenSource is only | ||
314 | // useful for tokens that never expire. | ||
315 | func StaticTokenSource(t *Token) TokenSource { | ||
316 | return staticTokenSource{t} | ||
317 | } | ||
318 | |||
319 | // staticTokenSource is a TokenSource that always returns the same Token. | ||
320 | type staticTokenSource struct { | ||
321 | t *Token | ||
322 | } | ||
323 | |||
324 | func (s staticTokenSource) Token() (*Token, error) { | ||
325 | return s.t, nil | ||
326 | } | ||
327 | |||
328 | // HTTPClient is the context key to use with golang.org/x/net/context's | ||
329 | // WithValue function to associate an *http.Client value with a context. | ||
330 | var HTTPClient internal.ContextKey | ||
331 | |||
332 | // NewClient creates an *http.Client from a Context and TokenSource. | ||
333 | // The returned client is not valid beyond the lifetime of the context. | ||
334 | // | ||
335 | // Note that if a custom *http.Client is provided via the Context it | ||
336 | // is used only for token acquisition and is not used to configure the | ||
337 | // *http.Client returned from NewClient. | ||
338 | // | ||
339 | // As a special case, if src is nil, a non-OAuth2 client is returned | ||
340 | // using the provided context. This exists to support related OAuth2 | ||
341 | // packages. | ||
342 | func NewClient(ctx context.Context, src TokenSource) *http.Client { | ||
343 | if src == nil { | ||
344 | return internal.ContextClient(ctx) | ||
345 | } | ||
346 | return &http.Client{ | ||
347 | Transport: &Transport{ | ||
348 | Base: internal.ContextClient(ctx).Transport, | ||
349 | Source: ReuseTokenSource(nil, src), | ||
350 | }, | ||
351 | } | ||
352 | } | ||
353 | |||
354 | // ReuseTokenSource returns a TokenSource which repeatedly returns the | ||
355 | // same token as long as it's valid, starting with t. | ||
356 | // When its cached token is invalid, a new token is obtained from src. | ||
357 | // | ||
358 | // ReuseTokenSource is typically used to reuse tokens from a cache | ||
359 | // (such as a file on disk) between runs of a program, rather than | ||
360 | // obtaining new tokens unnecessarily. | ||
361 | // | ||
362 | // The initial token t may be nil, in which case the TokenSource is | ||
363 | // wrapped in a caching version if it isn't one already. This also | ||
364 | // means it's always safe to wrap ReuseTokenSource around any other | ||
365 | // TokenSource without adverse effects. | ||
366 | func ReuseTokenSource(t *Token, src TokenSource) TokenSource { | ||
367 | // Don't wrap a reuseTokenSource in itself. That would work, | ||
368 | // but cause an unnecessary number of mutex operations. | ||
369 | // Just build the equivalent one. | ||
370 | if rt, ok := src.(*reuseTokenSource); ok { | ||
371 | if t == nil { | ||
372 | // Just use it directly. | ||
373 | return rt | ||
374 | } | ||
375 | src = rt.new | ||
376 | } | ||
377 | return &reuseTokenSource{ | ||
378 | t: t, | ||
379 | new: src, | ||
380 | } | ||
381 | } | ||
diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go new file mode 100644 index 0000000..8227203 --- /dev/null +++ b/vendor/golang.org/x/oauth2/token.go | |||
@@ -0,0 +1,178 @@ | |||
1 | // Copyright 2014 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 oauth2 | ||
6 | |||
7 | import ( | ||
8 | "context" | ||
9 | "fmt" | ||
10 | "net/http" | ||
11 | "net/url" | ||
12 | "strconv" | ||
13 | "strings" | ||
14 | "time" | ||
15 | |||
16 | "golang.org/x/oauth2/internal" | ||
17 | ) | ||
18 | |||
19 | // expiryDelta determines how earlier a token should be considered | ||
20 | // expired than its actual expiration time. It is used to avoid late | ||
21 | // expirations due to client-server time mismatches. | ||
22 | const expiryDelta = 10 * time.Second | ||
23 | |||
24 | // Token represents the credentials used to authorize | ||
25 | // the requests to access protected resources on the OAuth 2.0 | ||
26 | // provider's backend. | ||
27 | // | ||
28 | // Most users of this package should not access fields of Token | ||
29 | // directly. They're exported mostly for use by related packages | ||
30 | // implementing derivative OAuth2 flows. | ||
31 | type Token struct { | ||
32 | // AccessToken is the token that authorizes and authenticates | ||
33 | // the requests. | ||
34 | AccessToken string `json:"access_token"` | ||
35 | |||
36 | // TokenType is the type of token. | ||
37 | // The Type method returns either this or "Bearer", the default. | ||
38 | TokenType string `json:"token_type,omitempty"` | ||
39 | |||
40 | // RefreshToken is a token that's used by the application | ||
41 | // (as opposed to the user) to refresh the access token | ||
42 | // if it expires. | ||
43 | RefreshToken string `json:"refresh_token,omitempty"` | ||
44 | |||
45 | // Expiry is the optional expiration time of the access token. | ||
46 | // | ||
47 | // If zero, TokenSource implementations will reuse the same | ||
48 | // token forever and RefreshToken or equivalent | ||
49 | // mechanisms for that TokenSource will not be used. | ||
50 | Expiry time.Time `json:"expiry,omitempty"` | ||
51 | |||
52 | // raw optionally contains extra metadata from the server | ||
53 | // when updating a token. | ||
54 | raw interface{} | ||
55 | } | ||
56 | |||
57 | // Type returns t.TokenType if non-empty, else "Bearer". | ||
58 | func (t *Token) Type() string { | ||
59 | if strings.EqualFold(t.TokenType, "bearer") { | ||
60 | return "Bearer" | ||
61 | } | ||
62 | if strings.EqualFold(t.TokenType, "mac") { | ||
63 | return "MAC" | ||
64 | } | ||
65 | if strings.EqualFold(t.TokenType, "basic") { | ||
66 | return "Basic" | ||
67 | } | ||
68 | if t.TokenType != "" { | ||
69 | return t.TokenType | ||
70 | } | ||
71 | return "Bearer" | ||
72 | } | ||
73 | |||
74 | // SetAuthHeader sets the Authorization header to r using the access | ||
75 | // token in t. | ||
76 | // | ||
77 | // This method is unnecessary when using Transport or an HTTP Client | ||
78 | // returned by this package. | ||
79 | func (t *Token) SetAuthHeader(r *http.Request) { | ||
80 | r.Header.Set("Authorization", t.Type()+" "+t.AccessToken) | ||
81 | } | ||
82 | |||
83 | // WithExtra returns a new Token that's a clone of t, but using the | ||
84 | // provided raw extra map. This is only intended for use by packages | ||
85 | // implementing derivative OAuth2 flows. | ||
86 | func (t *Token) WithExtra(extra interface{}) *Token { | ||
87 | t2 := new(Token) | ||
88 | *t2 = *t | ||
89 | t2.raw = extra | ||
90 | return t2 | ||
91 | } | ||
92 | |||
93 | // Extra returns an extra field. | ||
94 | // Extra fields are key-value pairs returned by the server as a | ||
95 | // part of the token retrieval response. | ||
96 | func (t *Token) Extra(key string) interface{} { | ||
97 | if raw, ok := t.raw.(map[string]interface{}); ok { | ||
98 | return raw[key] | ||
99 | } | ||
100 | |||
101 | vals, ok := t.raw.(url.Values) | ||
102 | if !ok { | ||
103 | return nil | ||
104 | } | ||
105 | |||
106 | v := vals.Get(key) | ||
107 | switch s := strings.TrimSpace(v); strings.Count(s, ".") { | ||
108 | case 0: // Contains no "."; try to parse as int | ||
109 | if i, err := strconv.ParseInt(s, 10, 64); err == nil { | ||
110 | return i | ||
111 | } | ||
112 | case 1: // Contains a single "."; try to parse as float | ||
113 | if f, err := strconv.ParseFloat(s, 64); err == nil { | ||
114 | return f | ||
115 | } | ||
116 | } | ||
117 | |||
118 | return v | ||
119 | } | ||
120 | |||
121 | // timeNow is time.Now but pulled out as a variable for tests. | ||
122 | var timeNow = time.Now | ||
123 | |||
124 | // expired reports whether the token is expired. | ||
125 | // t must be non-nil. | ||
126 | func (t *Token) expired() bool { | ||
127 | if t.Expiry.IsZero() { | ||
128 | return false | ||
129 | } | ||
130 | return t.Expiry.Round(0).Add(-expiryDelta).Before(timeNow()) | ||
131 | } | ||
132 | |||
133 | // Valid reports whether t is non-nil, has an AccessToken, and is not expired. | ||
134 | func (t *Token) Valid() bool { | ||
135 | return t != nil && t.AccessToken != "" && !t.expired() | ||
136 | } | ||
137 | |||
138 | // tokenFromInternal maps an *internal.Token struct into | ||
139 | // a *Token struct. | ||
140 | func tokenFromInternal(t *internal.Token) *Token { | ||
141 | if t == nil { | ||
142 | return nil | ||
143 | } | ||
144 | return &Token{ | ||
145 | AccessToken: t.AccessToken, | ||
146 | TokenType: t.TokenType, | ||
147 | RefreshToken: t.RefreshToken, | ||
148 | Expiry: t.Expiry, | ||
149 | raw: t.Raw, | ||
150 | } | ||
151 | } | ||
152 | |||
153 | // retrieveToken takes a *Config and uses that to retrieve an *internal.Token. | ||
154 | // This token is then mapped from *internal.Token into an *oauth2.Token which is returned along | ||
155 | // with an error.. | ||
156 | func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { | ||
157 | tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle)) | ||
158 | if err != nil { | ||
159 | if rErr, ok := err.(*internal.RetrieveError); ok { | ||
160 | return nil, (*RetrieveError)(rErr) | ||
161 | } | ||
162 | return nil, err | ||
163 | } | ||
164 | return tokenFromInternal(tk), nil | ||
165 | } | ||
166 | |||
167 | // RetrieveError is the error returned when the token endpoint returns a | ||
168 | // non-2XX HTTP status code. | ||
169 | type RetrieveError struct { | ||
170 | Response *http.Response | ||
171 | // Body is the body that was consumed by reading Response.Body. | ||
172 | // It may be truncated. | ||
173 | Body []byte | ||
174 | } | ||
175 | |||
176 | func (r *RetrieveError) Error() string { | ||
177 | return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) | ||
178 | } | ||
diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go new file mode 100644 index 0000000..aa0d34f --- /dev/null +++ b/vendor/golang.org/x/oauth2/transport.go | |||
@@ -0,0 +1,144 @@ | |||
1 | // Copyright 2014 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 oauth2 | ||
6 | |||
7 | import ( | ||
8 | "errors" | ||
9 | "io" | ||
10 | "net/http" | ||
11 | "sync" | ||
12 | ) | ||
13 | |||
14 | // Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests, | ||
15 | // wrapping a base RoundTripper and adding an Authorization header | ||
16 | // with a token from the supplied Sources. | ||
17 | // | ||
18 | // Transport is a low-level mechanism. Most code will use the | ||
19 | // higher-level Config.Client method instead. | ||
20 | type Transport struct { | ||
21 | // Source supplies the token to add to outgoing requests' | ||
22 | // Authorization headers. | ||
23 | Source TokenSource | ||
24 | |||
25 | // Base is the base RoundTripper used to make HTTP requests. | ||
26 | // If nil, http.DefaultTransport is used. | ||
27 | Base http.RoundTripper | ||
28 | |||
29 | mu sync.Mutex // guards modReq | ||
30 | modReq map[*http.Request]*http.Request // original -> modified | ||
31 | } | ||
32 | |||
33 | // RoundTrip authorizes and authenticates the request with an | ||
34 | // access token from Transport's Source. | ||
35 | func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { | ||
36 | reqBodyClosed := false | ||
37 | if req.Body != nil { | ||
38 | defer func() { | ||
39 | if !reqBodyClosed { | ||
40 | req.Body.Close() | ||
41 | } | ||
42 | }() | ||
43 | } | ||
44 | |||
45 | if t.Source == nil { | ||
46 | return nil, errors.New("oauth2: Transport's Source is nil") | ||
47 | } | ||
48 | token, err := t.Source.Token() | ||
49 | if err != nil { | ||
50 | return nil, err | ||
51 | } | ||
52 | |||
53 | req2 := cloneRequest(req) // per RoundTripper contract | ||
54 | token.SetAuthHeader(req2) | ||
55 | t.setModReq(req, req2) | ||
56 | res, err := t.base().RoundTrip(req2) | ||
57 | |||
58 | // req.Body is assumed to have been closed by the base RoundTripper. | ||
59 | reqBodyClosed = true | ||
60 | |||
61 | if err != nil { | ||
62 | t.setModReq(req, nil) | ||
63 | return nil, err | ||
64 | } | ||
65 | res.Body = &onEOFReader{ | ||
66 | rc: res.Body, | ||
67 | fn: func() { t.setModReq(req, nil) }, | ||
68 | } | ||
69 | return res, nil | ||
70 | } | ||
71 | |||
72 | // CancelRequest cancels an in-flight request by closing its connection. | ||
73 | func (t *Transport) CancelRequest(req *http.Request) { | ||
74 | type canceler interface { | ||
75 | CancelRequest(*http.Request) | ||
76 | } | ||
77 | if cr, ok := t.base().(canceler); ok { | ||
78 | t.mu.Lock() | ||
79 | modReq := t.modReq[req] | ||
80 | delete(t.modReq, req) | ||
81 | t.mu.Unlock() | ||
82 | cr.CancelRequest(modReq) | ||
83 | } | ||
84 | } | ||
85 | |||
86 | func (t *Transport) base() http.RoundTripper { | ||
87 | if t.Base != nil { | ||
88 | return t.Base | ||
89 | } | ||
90 | return http.DefaultTransport | ||
91 | } | ||
92 | |||
93 | func (t *Transport) setModReq(orig, mod *http.Request) { | ||
94 | t.mu.Lock() | ||
95 | defer t.mu.Unlock() | ||
96 | if t.modReq == nil { | ||
97 | t.modReq = make(map[*http.Request]*http.Request) | ||
98 | } | ||
99 | if mod == nil { | ||
100 | delete(t.modReq, orig) | ||
101 | } else { | ||
102 | t.modReq[orig] = mod | ||
103 | } | ||
104 | } | ||
105 | |||
106 | // cloneRequest returns a clone of the provided *http.Request. | ||
107 | // The clone is a shallow copy of the struct and its Header map. | ||
108 | func cloneRequest(r *http.Request) *http.Request { | ||
109 | // shallow copy of the struct | ||
110 | r2 := new(http.Request) | ||
111 | *r2 = *r | ||
112 | // deep copy of the Header | ||
113 | r2.Header = make(http.Header, len(r.Header)) | ||
114 | for k, s := range r.Header { | ||
115 | r2.Header[k] = append([]string(nil), s...) | ||
116 | } | ||
117 | return r2 | ||
118 | } | ||
119 | |||
120 | type onEOFReader struct { | ||
121 | rc io.ReadCloser | ||
122 | fn func() | ||
123 | } | ||
124 | |||
125 | func (r *onEOFReader) Read(p []byte) (n int, err error) { | ||
126 | n, err = r.rc.Read(p) | ||
127 | if err == io.EOF { | ||
128 | r.runFunc() | ||
129 | } | ||
130 | return | ||
131 | } | ||
132 | |||
133 | func (r *onEOFReader) Close() error { | ||
134 | err := r.rc.Close() | ||
135 | r.runFunc() | ||
136 | return err | ||
137 | } | ||
138 | |||
139 | func (r *onEOFReader) runFunc() { | ||
140 | if fn := r.fn; fn != nil { | ||
141 | fn() | ||
142 | r.fn = nil | ||
143 | } | ||
144 | } | ||