aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/golang.org/x
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x')
-rw-r--r--vendor/golang.org/x/net/http2/server.go11
-rw-r--r--vendor/golang.org/x/oauth2/.travis.yml13
-rw-r--r--vendor/golang.org/x/oauth2/AUTHORS3
-rw-r--r--vendor/golang.org/x/oauth2/CONTRIBUTING.md31
-rw-r--r--vendor/golang.org/x/oauth2/CONTRIBUTORS3
-rw-r--r--vendor/golang.org/x/oauth2/LICENSE27
-rw-r--r--vendor/golang.org/x/oauth2/README.md77
-rw-r--r--vendor/golang.org/x/oauth2/amazon/amazon.go16
-rw-r--r--vendor/golang.org/x/oauth2/bitbucket/bitbucket.go16
-rw-r--r--vendor/golang.org/x/oauth2/client_appengine.go25
-rw-r--r--vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go104
-rw-r--r--vendor/golang.org/x/oauth2/clientcredentials/clientcredentials_test.go97
-rw-r--r--vendor/golang.org/x/oauth2/example_test.go89
-rw-r--r--vendor/golang.org/x/oauth2/facebook/facebook.go16
-rw-r--r--vendor/golang.org/x/oauth2/fitbit/fitbit.go16
-rw-r--r--vendor/golang.org/x/oauth2/foursquare/foursquare.go16
-rw-r--r--vendor/golang.org/x/oauth2/github/github.go16
-rw-r--r--vendor/golang.org/x/oauth2/google/appengine.go89
-rw-r--r--vendor/golang.org/x/oauth2/google/appengine_hook.go14
-rw-r--r--vendor/golang.org/x/oauth2/google/appengineflex_hook.go11
-rw-r--r--vendor/golang.org/x/oauth2/google/default.go137
-rw-r--r--vendor/golang.org/x/oauth2/google/example_test.go150
-rw-r--r--vendor/golang.org/x/oauth2/google/google.go202
-rw-r--r--vendor/golang.org/x/oauth2/google/google_test.go116
-rw-r--r--vendor/golang.org/x/oauth2/google/jwt.go74
-rw-r--r--vendor/golang.org/x/oauth2/google/jwt_test.go91
-rw-r--r--vendor/golang.org/x/oauth2/google/sdk.go172
-rw-r--r--vendor/golang.org/x/oauth2/google/sdk_test.go46
-rw-r--r--vendor/golang.org/x/oauth2/google/testdata/gcloud/credentials122
-rw-r--r--vendor/golang.org/x/oauth2/google/testdata/gcloud/properties2
-rw-r--r--vendor/golang.org/x/oauth2/heroku/heroku.go16
-rw-r--r--vendor/golang.org/x/oauth2/hipchat/hipchat.go60
-rw-r--r--vendor/golang.org/x/oauth2/internal/doc.go6
-rw-r--r--vendor/golang.org/x/oauth2/internal/oauth2.go75
-rw-r--r--vendor/golang.org/x/oauth2/internal/oauth2_test.go61
-rw-r--r--vendor/golang.org/x/oauth2/internal/token.go251
-rw-r--r--vendor/golang.org/x/oauth2/internal/token_test.go104
-rw-r--r--vendor/golang.org/x/oauth2/internal/transport.go68
-rw-r--r--vendor/golang.org/x/oauth2/internal/transport_test.go38
-rw-r--r--vendor/golang.org/x/oauth2/jws/jws.go182
-rw-r--r--vendor/golang.org/x/oauth2/jws/jws_test.go46
-rw-r--r--vendor/golang.org/x/oauth2/jwt/example_test.go33
-rw-r--r--vendor/golang.org/x/oauth2/jwt/jwt.go159
-rw-r--r--vendor/golang.org/x/oauth2/jwt/jwt_test.go190
-rw-r--r--vendor/golang.org/x/oauth2/linkedin/linkedin.go16
-rw-r--r--vendor/golang.org/x/oauth2/mediamath/mediamath.go22
-rw-r--r--vendor/golang.org/x/oauth2/microsoft/microsoft.go16
-rw-r--r--vendor/golang.org/x/oauth2/oauth2.go344
-rw-r--r--vendor/golang.org/x/oauth2/oauth2_test.go490
-rw-r--r--vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go16
-rw-r--r--vendor/golang.org/x/oauth2/paypal/paypal.go22
-rw-r--r--vendor/golang.org/x/oauth2/slack/slack.go16
-rw-r--r--vendor/golang.org/x/oauth2/token.go158
-rw-r--r--vendor/golang.org/x/oauth2/token_test.go72
-rw-r--r--vendor/golang.org/x/oauth2/transport.go132
-rw-r--r--vendor/golang.org/x/oauth2/transport_test.go108
-rw-r--r--vendor/golang.org/x/oauth2/uber/uber.go16
-rw-r--r--vendor/golang.org/x/oauth2/vk/vk.go16
-rw-r--r--vendor/golang.org/x/oauth2/yandex/yandex.go16
-rw-r--r--vendor/golang.org/x/sys/unix/dev_darwin_test.go2
-rw-r--r--vendor/golang.org/x/sys/unix/dev_dragonfly_test.go2
-rw-r--r--vendor/golang.org/x/sys/unix/dev_linux_test.go2
-rw-r--r--vendor/golang.org/x/sys/unix/dev_netbsd_test.go2
-rw-r--r--vendor/golang.org/x/sys/unix/dev_openbsd_test.go2
-rw-r--r--vendor/golang.org/x/sys/unix/dev_solaris_test.go2
-rw-r--r--vendor/golang.org/x/sys/unix/syscall_darwin_arm.go4
-rw-r--r--vendor/golang.org/x/sys/windows/types_windows.go23
67 files changed, 4583 insertions, 7 deletions
diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go
index 3e705a0..4c8ee56 100644
--- a/vendor/golang.org/x/net/http2/server.go
+++ b/vendor/golang.org/x/net/http2/server.go
@@ -652,7 +652,7 @@ func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
if err == nil {
return
}
- if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) {
+ if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {
// Boring, expected errors.
sc.vlogf(format, args...)
} else {
@@ -897,8 +897,11 @@ func (sc *serverConn) sendServeMsg(msg interface{}) {
}
}
-// readPreface reads the ClientPreface greeting from the peer
-// or returns an error on timeout or an invalid greeting.
+var errPrefaceTimeout = errors.New("timeout waiting for client preface")
+
+// readPreface reads the ClientPreface greeting from the peer or
+// returns errPrefaceTimeout on timeout, or an error if the greeting
+// is invalid.
func (sc *serverConn) readPreface() error {
errc := make(chan error, 1)
go func() {
@@ -916,7 +919,7 @@ func (sc *serverConn) readPreface() error {
defer timer.Stop()
select {
case <-timer.C:
- return errors.New("timeout waiting for client preface")
+ return errPrefaceTimeout
case err := <-errc:
if err == nil {
if VerboseLogs {
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 @@
+language: go
+
+go:
+ - tip
+
+install:
+ - export GOPATH="$HOME/gopath"
+ - mkdir -p "$GOPATH/src/golang.org/x"
+ - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2"
+ - go get -v -t -d golang.org/x/oauth2/...
+
+script:
+ - 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 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# 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..46aa2b1
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+
+## Filing issues
+
+When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+**We do not accept GitHub pull requests**
+(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
+
+Unless otherwise noted, the Go source files are distributed under
+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 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# 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 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+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..eb8dcee
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/README.md
@@ -0,0 +1,77 @@
+# OAuth2 for Go
+
+[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2)
+[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2)
+
+oauth2 package contains a client implementation for OAuth 2.0 spec.
+
+## Installation
+
+~~~~
+go get golang.org/x/oauth2
+~~~~
+
+Or you can manually git clone the repository to
+`$(go env GOPATH)/src/golang.org/x/oauth2`.
+
+See godoc for further documentation and examples.
+
+* [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2)
+* [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google)
+
+
+## App Engine
+
+In change 96e89be (March 2015), we removed the `oauth2.Context2` type in favor
+of the [`context.Context`](https://golang.org/x/net/context#Context) type from
+the `golang.org/x/net/context` package
+
+This means it's no longer possible to use the "Classic App Engine"
+`appengine.Context` type with the `oauth2` package. (You're using
+Classic App Engine if you import the package `"appengine"`.)
+
+To work around this, you may use the new `"google.golang.org/appengine"`
+package. This package has almost the same API as the `"appengine"` package,
+but it can be fetched with `go get` and used on "Managed VMs" and well as
+Classic App Engine.
+
+See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app)
+for information on updating your app.
+
+If you don't want to update your entire app to use the new App Engine packages,
+you may use both sets of packages in parallel, using only the new packages
+with the `oauth2` package.
+
+```go
+import (
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google"
+ newappengine "google.golang.org/appengine"
+ newurlfetch "google.golang.org/appengine/urlfetch"
+
+ "appengine"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ var c appengine.Context = appengine.NewContext(r)
+ c.Infof("Logging a message with the old package")
+
+ var ctx context.Context = newappengine.NewContext(r)
+ client := &http.Client{
+ Transport: &oauth2.Transport{
+ Source: google.AppEngineTokenSource(ctx, "scope"),
+ Base: &newurlfetch.Transport{Context: ctx},
+ },
+ }
+ client.Get("...")
+}
+```
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit changes to
+this repository, see https://golang.org/doc/contribute.html.
+
+The main issue tracker for the oauth2 repository is located at
+https://github.com/golang/oauth2/issues.
diff --git a/vendor/golang.org/x/oauth2/amazon/amazon.go b/vendor/golang.org/x/oauth2/amazon/amazon.go
new file mode 100644
index 0000000..d21da11
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/amazon/amazon.go
@@ -0,0 +1,16 @@
+// Copyright 2017 The oauth2 Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package amazon provides constants for using OAuth2 to access Amazon.
+package amazon
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Amazon's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.amazon.com/ap/oa",
+ TokenURL: "https://api.amazon.com/auth/o2/token",
+}
diff --git a/vendor/golang.org/x/oauth2/bitbucket/bitbucket.go b/vendor/golang.org/x/oauth2/bitbucket/bitbucket.go
new file mode 100644
index 0000000..44af1f1
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/bitbucket/bitbucket.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The oauth2 Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bitbucket provides constants for using OAuth2 to access Bitbucket.
+package bitbucket
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Bitbucket's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://bitbucket.org/site/oauth2/authorize",
+ TokenURL: "https://bitbucket.org/site/oauth2/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/client_appengine.go b/vendor/golang.org/x/oauth2/client_appengine.go
new file mode 100644
index 0000000..8962c49
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/client_appengine.go
@@ -0,0 +1,25 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+// App Engine hooks.
+
+package oauth2
+
+import (
+ "net/http"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2/internal"
+ "google.golang.org/appengine/urlfetch"
+)
+
+func init() {
+ internal.RegisterContextClientFunc(contextClientAppEngine)
+}
+
+func contextClientAppEngine(ctx context.Context) (*http.Client, error) {
+ return urlfetch.Client(ctx), nil
+}
diff --git a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
new file mode 100644
index 0000000..53a96b6
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
@@ -0,0 +1,104 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package clientcredentials implements the OAuth2.0 "client credentials" token flow,
+// also known as the "two-legged OAuth 2.0".
+//
+// This should be used when the client is acting on its own behalf or when the client
+// is the resource owner. It may also be used when requesting access to protected
+// resources based on an authorization previously arranged with the authorization
+// server.
+//
+// See https://tools.ietf.org/html/rfc6749#section-4.4
+package clientcredentials // import "golang.org/x/oauth2/clientcredentials"
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+)
+
+// Config describes a 2-legged OAuth2 flow, with both the
+// client application information and the server's endpoint URLs.
+type Config struct {
+ // ClientID is the application's ID.
+ ClientID string
+
+ // ClientSecret is the application's secret.
+ ClientSecret string
+
+ // TokenURL is the resource server's token endpoint
+ // URL. This is a constant specific to each server.
+ TokenURL string
+
+ // Scope specifies optional requested permissions.
+ Scopes []string
+
+ // EndpointParams specifies additional parameters for requests to the token endpoint.
+ EndpointParams url.Values
+}
+
+// Token uses client credentials to retrieve a token.
+// The HTTP client to use is derived from the context.
+// If nil, http.DefaultClient is used.
+func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) {
+ return c.TokenSource(ctx).Token()
+}
+
+// Client returns an HTTP client using the provided token.
+// The token will auto-refresh as necessary. The underlying
+// HTTP transport will be obtained using the provided context.
+// The returned client and its Transport should not be modified.
+func (c *Config) Client(ctx context.Context) *http.Client {
+ return oauth2.NewClient(ctx, c.TokenSource(ctx))
+}
+
+// TokenSource returns a TokenSource that returns t until t expires,
+// automatically refreshing it as necessary using the provided context and the
+// client ID and client secret.
+//
+// Most users will use Config.Client instead.
+func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
+ source := &tokenSource{
+ ctx: ctx,
+ conf: c,
+ }
+ return oauth2.ReuseTokenSource(nil, source)
+}
+
+type tokenSource struct {
+ ctx context.Context
+ conf *Config
+}
+
+// Token refreshes the token by using a new client credentials request.
+// tokens received this way do not include a refresh token
+func (c *tokenSource) Token() (*oauth2.Token, error) {
+ v := url.Values{
+ "grant_type": {"client_credentials"},
+ "scope": internal.CondVal(strings.Join(c.conf.Scopes, " ")),
+ }
+ for k, p := range c.conf.EndpointParams {
+ if _, ok := v[k]; ok {
+ return nil, fmt.Errorf("oauth2: cannot overwrite parameter %q", k)
+ }
+ v[k] = p
+ }
+ tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v)
+ if err != nil {
+ return nil, err
+ }
+ t := &oauth2.Token{
+ AccessToken: tk.AccessToken,
+ TokenType: tk.TokenType,
+ RefreshToken: tk.RefreshToken,
+ Expiry: tk.Expiry,
+ }
+ return t.WithExtra(tk.Raw), nil
+}
diff --git a/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials_test.go b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials_test.go
new file mode 100644
index 0000000..108520c
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/clientcredentials/clientcredentials_test.go
@@ -0,0 +1,97 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package clientcredentials
+
+import (
+ "context"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "testing"
+)
+
+func newConf(serverURL string) *Config {
+ return &Config{
+ ClientID: "CLIENT_ID",
+ ClientSecret: "CLIENT_SECRET",
+ Scopes: []string{"scope1", "scope2"},
+ TokenURL: serverURL + "/token",
+ EndpointParams: url.Values{"audience": {"audience1"}},
+ }
+}
+
+type mockTransport struct {
+ rt func(req *http.Request) (resp *http.Response, err error)
+}
+
+func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
+ return t.rt(req)
+}
+
+func TestTokenRequest(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.String() != "/token" {
+ t.Errorf("authenticate client request URL = %q; want %q", r.URL, "/token")
+ }
+ headerAuth := r.Header.Get("Authorization")
+ if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" {
+ t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
+ }
+ if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want {
+ t.Errorf("Content-Type header = %q; want %q", got, want)
+ }
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ r.Body.Close()
+ }
+ if err != nil {
+ t.Errorf("failed reading request body: %s.", err)
+ }
+ if string(body) != "audience=audience1&grant_type=client_credentials&scope=scope1+scope2" {
+ t.Errorf("payload = %q; want %q", string(body), "grant_type=client_credentials&scope=scope1+scope2")
+ }
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&token_type=bearer"))
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ tok, err := conf.Token(context.Background())
+ if err != nil {
+ t.Error(err)
+ }
+ if !tok.Valid() {
+ t.Fatalf("token invalid. got: %#v", tok)
+ }
+ if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" {
+ t.Errorf("Access token = %q; want %q", tok.AccessToken, "90d64460d14870c08c81352a05dedd3465940a7c")
+ }
+ if tok.TokenType != "bearer" {
+ t.Errorf("token type = %q; want %q", tok.TokenType, "bearer")
+ }
+}
+
+func TestTokenRefreshRequest(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.String() == "/somethingelse" {
+ return
+ }
+ if r.URL.String() != "/token" {
+ t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL)
+ }
+ headerContentType := r.Header.Get("Content-Type")
+ if headerContentType != "application/x-www-form-urlencoded" {
+ t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
+ }
+ body, _ := ioutil.ReadAll(r.Body)
+ if string(body) != "audience=audience1&grant_type=client_credentials&scope=scope1+scope2" {
+ t.Errorf("Unexpected refresh token payload, %v is found.", string(body))
+ }
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ c := conf.Client(context.Background())
+ c.Get(ts.URL + "/somethingelse")
+}
diff --git a/vendor/golang.org/x/oauth2/example_test.go b/vendor/golang.org/x/oauth2/example_test.go
new file mode 100644
index 0000000..fc2f793
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/example_test.go
@@ -0,0 +1,89 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2_test
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "net/http"
+ "time"
+
+ "golang.org/x/oauth2"
+)
+
+func ExampleConfig() {
+ ctx := context.Background()
+ conf := &oauth2.Config{
+ ClientID: "YOUR_CLIENT_ID",
+ ClientSecret: "YOUR_CLIENT_SECRET",
+ Scopes: []string{"SCOPE1", "SCOPE2"},
+ Endpoint: oauth2.Endpoint{
+ AuthURL: "https://provider.com/o/oauth2/auth",
+ TokenURL: "https://provider.com/o/oauth2/token",
+ },
+ }
+
+ // Redirect user to consent page to ask for permission
+ // for the scopes specified above.
+ url := conf.AuthCodeURL("state", oauth2.AccessTypeOffline)
+ fmt.Printf("Visit the URL for the auth dialog: %v", url)
+
+ // Use the authorization code that is pushed to the redirect
+ // URL. Exchange will do the handshake to retrieve the
+ // initial access token. The HTTP Client returned by
+ // conf.Client will refresh the token as necessary.
+ var code string
+ if _, err := fmt.Scan(&code); err != nil {
+ log.Fatal(err)
+ }
+ tok, err := conf.Exchange(ctx, code)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ client := conf.Client(ctx, tok)
+ client.Get("...")
+}
+
+func ExampleConfig_customHTTP() {
+ ctx := context.Background()
+
+ conf := &oauth2.Config{
+ ClientID: "YOUR_CLIENT_ID",
+ ClientSecret: "YOUR_CLIENT_SECRET",
+ Scopes: []string{"SCOPE1", "SCOPE2"},
+ Endpoint: oauth2.Endpoint{
+ TokenURL: "https://provider.com/o/oauth2/token",
+ AuthURL: "https://provider.com/o/oauth2/auth",
+ },
+ }
+
+ // Redirect user to consent page to ask for permission
+ // for the scopes specified above.
+ url := conf.AuthCodeURL("state", oauth2.AccessTypeOffline)
+ fmt.Printf("Visit the URL for the auth dialog: %v", url)
+
+ // Use the authorization code that is pushed to the redirect
+ // URL. Exchange will do the handshake to retrieve the
+ // initial access token. The HTTP Client returned by
+ // conf.Client will refresh the token as necessary.
+ var code string
+ if _, err := fmt.Scan(&code); err != nil {
+ log.Fatal(err)
+ }
+
+ // Use the custom HTTP client when requesting a token.
+ httpClient := &http.Client{Timeout: 2 * time.Second}
+ ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
+
+ tok, err := conf.Exchange(ctx, code)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ client := conf.Client(ctx, tok)
+ _ = client
+}
diff --git a/vendor/golang.org/x/oauth2/facebook/facebook.go b/vendor/golang.org/x/oauth2/facebook/facebook.go
new file mode 100644
index 0000000..14c801a
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/facebook/facebook.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package facebook provides constants for using OAuth2 to access Facebook.
+package facebook // import "golang.org/x/oauth2/facebook"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Facebook's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.facebook.com/dialog/oauth",
+ TokenURL: "https://graph.facebook.com/oauth/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/fitbit/fitbit.go b/vendor/golang.org/x/oauth2/fitbit/fitbit.go
new file mode 100644
index 0000000..b31b82a
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/fitbit/fitbit.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package fitbit provides constants for using OAuth2 to access the Fitbit API.
+package fitbit // import "golang.org/x/oauth2/fitbit"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is the Fitbit API's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.fitbit.com/oauth2/authorize",
+ TokenURL: "https://api.fitbit.com/oauth2/token",
+}
diff --git a/vendor/golang.org/x/oauth2/foursquare/foursquare.go b/vendor/golang.org/x/oauth2/foursquare/foursquare.go
new file mode 100644
index 0000000..d2fa099
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/foursquare/foursquare.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package foursquare provides constants for using OAuth2 to access Foursquare.
+package foursquare // import "golang.org/x/oauth2/foursquare"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Foursquare's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://foursquare.com/oauth2/authorize",
+ TokenURL: "https://foursquare.com/oauth2/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/github/github.go b/vendor/golang.org/x/oauth2/github/github.go
new file mode 100644
index 0000000..f297801
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/github/github.go
@@ -0,0 +1,16 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package github provides constants for using OAuth2 to access Github.
+package github // import "golang.org/x/oauth2/github"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Github's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://github.com/login/oauth/authorize",
+ TokenURL: "https://github.com/login/oauth/access_token",
+}
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..50d918b
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengine.go
@@ -0,0 +1,89 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+)
+
+// appengineFlex is set at init time by appengineflex_hook.go. If true, we are on App Engine Flex.
+var appengineFlex bool
+
+// Set at init time by appengine_hook.go. If nil, we're not on App Engine.
+var appengineTokenFunc func(c context.Context, scopes ...string) (token string, expiry time.Time, err error)
+
+// Set at init time by appengine_hook.go. If nil, we're not on App Engine.
+var appengineAppIDFunc func(c context.Context) string
+
+// AppEngineTokenSource returns a token source that fetches tokens
+// issued to the current App Engine application's service account.
+// If you are implementing a 3-legged OAuth 2.0 flow on App Engine
+// that involves user accounts, see oauth2.Config instead.
+//
+// The provided context must have come from appengine.NewContext.
+func AppEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource {
+ if appengineTokenFunc == nil {
+ panic("google: AppEngineTokenSource can only be used on App Engine.")
+ }
+ scopes := append([]string{}, scope...)
+ sort.Strings(scopes)
+ return &appEngineTokenSource{
+ ctx: ctx,
+ scopes: scopes,
+ key: strings.Join(scopes, " "),
+ }
+}
+
+// aeTokens helps the fetched tokens to be reused until their expiration.
+var (
+ aeTokensMu sync.Mutex
+ aeTokens = make(map[string]*tokenLock) // key is space-separated scopes
+)
+
+type tokenLock struct {
+ mu sync.Mutex // guards t; held while fetching or updating t
+ t *oauth2.Token
+}
+
+type appEngineTokenSource struct {
+ ctx context.Context
+ scopes []string
+ key string // to aeTokens map; space-separated scopes
+}
+
+func (ts *appEngineTokenSource) Token() (*oauth2.Token, error) {
+ if appengineTokenFunc == nil {
+ panic("google: AppEngineTokenSource can only be used on App Engine.")
+ }
+
+ aeTokensMu.Lock()
+ tok, ok := aeTokens[ts.key]
+ if !ok {
+ tok = &tokenLock{}
+ aeTokens[ts.key] = tok
+ }
+ aeTokensMu.Unlock()
+
+ tok.mu.Lock()
+ defer tok.mu.Unlock()
+ if tok.t.Valid() {
+ return tok.t, nil
+ }
+ access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...)
+ if err != nil {
+ return nil, err
+ }
+ tok.t = &oauth2.Token{
+ AccessToken: access,
+ Expiry: exp,
+ }
+ return tok.t, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/appengine_hook.go b/vendor/golang.org/x/oauth2/google/appengine_hook.go
new file mode 100644
index 0000000..56669ea
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengine_hook.go
@@ -0,0 +1,14 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine appenginevm
+
+package google
+
+import "google.golang.org/appengine"
+
+func init() {
+ appengineTokenFunc = appengine.AccessToken
+ appengineAppIDFunc = appengine.AppID
+}
diff --git a/vendor/golang.org/x/oauth2/google/appengineflex_hook.go b/vendor/golang.org/x/oauth2/google/appengineflex_hook.go
new file mode 100644
index 0000000..5d0231a
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengineflex_hook.go
@@ -0,0 +1,11 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appenginevm
+
+package google
+
+func init() {
+ appengineFlex = true // Flex doesn't support appengine.AccessToken; depend on metadata server.
+}
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..b4b6274
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/default.go
@@ -0,0 +1,137 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "cloud.google.com/go/compute/metadata"
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+)
+
+// DefaultCredentials holds "Application Default Credentials".
+// For more details, see:
+// https://developers.google.com/accounts/docs/application-default-credentials
+type DefaultCredentials struct {
+ ProjectID string // may be empty
+ TokenSource oauth2.TokenSource
+
+ // JSON contains the raw bytes from a JSON credentials file.
+ // This field may be nil if authentication is provided by the
+ // environment and not with a credentials file, e.g. when code is
+ // running on Google Cloud Platform.
+ JSON []byte
+}
+
+// DefaultClient returns an HTTP Client that uses the
+// DefaultTokenSource to obtain authentication credentials.
+func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) {
+ ts, err := DefaultTokenSource(ctx, scope...)
+ if err != nil {
+ return nil, err
+ }
+ return oauth2.NewClient(ctx, ts), nil
+}
+
+// DefaultTokenSource returns the token source for
+// "Application Default Credentials".
+// It is a shortcut for FindDefaultCredentials(ctx, scope).TokenSource.
+func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) {
+ creds, err := FindDefaultCredentials(ctx, scope...)
+ if err != nil {
+ return nil, err
+ }
+ return creds.TokenSource, nil
+}
+
+// FindDefaultCredentials searches for "Application Default Credentials".
+//
+// It looks for credentials in the following places,
+// preferring the first location found:
+//
+// 1. A JSON file whose path is specified by the
+// GOOGLE_APPLICATION_CREDENTIALS environment variable.
+// 2. A JSON file in a location known to the gcloud command-line tool.
+// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json.
+// On other systems, $HOME/.config/gcloud/application_default_credentials.json.
+// 3. On Google App Engine it uses the appengine.AccessToken function.
+// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches
+// credentials from the metadata server.
+// (In this final case any provided scopes are ignored.)
+func FindDefaultCredentials(ctx context.Context, scope ...string) (*DefaultCredentials, error) {
+ // First, try the environment variable.
+ const envVar = "GOOGLE_APPLICATION_CREDENTIALS"
+ if filename := os.Getenv(envVar); filename != "" {
+ creds, err := readCredentialsFile(ctx, filename, scope)
+ if err != nil {
+ return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err)
+ }
+ return creds, nil
+ }
+
+ // Second, try a well-known file.
+ filename := wellKnownFile()
+ if creds, err := readCredentialsFile(ctx, filename, scope); err == nil {
+ return creds, nil
+ } else if !os.IsNotExist(err) {
+ return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err)
+ }
+
+ // Third, if we're on Google App Engine use those credentials.
+ if appengineTokenFunc != nil && !appengineFlex {
+ return &DefaultCredentials{
+ ProjectID: appengineAppIDFunc(ctx),
+ TokenSource: AppEngineTokenSource(ctx, scope...),
+ }, nil
+ }
+
+ // Fourth, if we're on Google Compute Engine use the metadata server.
+ if metadata.OnGCE() {
+ id, _ := metadata.ProjectID()
+ return &DefaultCredentials{
+ ProjectID: id,
+ TokenSource: ComputeTokenSource(""),
+ }, nil
+ }
+
+ // None are found; return helpful error.
+ const url = "https://developers.google.com/accounts/docs/application-default-credentials"
+ return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url)
+}
+
+func wellKnownFile() string {
+ const f = "application_default_credentials.json"
+ if runtime.GOOS == "windows" {
+ return filepath.Join(os.Getenv("APPDATA"), "gcloud", f)
+ }
+ return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f)
+}
+
+func readCredentialsFile(ctx context.Context, filename string, scopes []string) (*DefaultCredentials, error) {
+ b, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ var f credentialsFile
+ if err := json.Unmarshal(b, &f); err != nil {
+ return nil, err
+ }
+ ts, err := f.tokenSource(ctx, append([]string(nil), scopes...))
+ if err != nil {
+ return nil, err
+ }
+ return &DefaultCredentials{
+ ProjectID: f.ProjectID,
+ TokenSource: ts,
+ JSON: b,
+ }, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/example_test.go b/vendor/golang.org/x/oauth2/google/example_test.go
new file mode 100644
index 0000000..92bc3b4
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/example_test.go
@@ -0,0 +1,150 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appenginevm appengine
+
+package google_test
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net/http"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google"
+ "golang.org/x/oauth2/jwt"
+ "google.golang.org/appengine"
+ "google.golang.org/appengine/urlfetch"
+)
+
+func ExampleDefaultClient() {
+ client, err := google.DefaultClient(oauth2.NoContext,
+ "https://www.googleapis.com/auth/devstorage.full_control")
+ if err != nil {
+ log.Fatal(err)
+ }
+ client.Get("...")
+}
+
+func Example_webServer() {
+ // Your credentials should be obtained from the Google
+ // Developer Console (https://console.developers.google.com).
+ conf := &oauth2.Config{
+ ClientID: "YOUR_CLIENT_ID",
+ ClientSecret: "YOUR_CLIENT_SECRET",
+ RedirectURL: "YOUR_REDIRECT_URL",
+ Scopes: []string{
+ "https://www.googleapis.com/auth/bigquery",
+ "https://www.googleapis.com/auth/blogger",
+ },
+ Endpoint: google.Endpoint,
+ }
+ // Redirect user to Google's consent page to ask for permission
+ // for the scopes specified above.
+ url := conf.AuthCodeURL("state")
+ fmt.Printf("Visit the URL for the auth dialog: %v", url)
+
+ // Handle the exchange code to initiate a transport.
+ tok, err := conf.Exchange(oauth2.NoContext, "authorization-code")
+ if err != nil {
+ log.Fatal(err)
+ }
+ client := conf.Client(oauth2.NoContext, tok)
+ client.Get("...")
+}
+
+func ExampleJWTConfigFromJSON() {
+ // Your credentials should be obtained from the Google
+ // Developer Console (https://console.developers.google.com).
+ // Navigate to your project, then see the "Credentials" page
+ // under "APIs & Auth".
+ // To create a service account client, click "Create new Client ID",
+ // select "Service Account", and click "Create Client ID". A JSON
+ // key file will then be downloaded to your computer.
+ data, err := ioutil.ReadFile("/path/to/your-project-key.json")
+ if err != nil {
+ log.Fatal(err)
+ }
+ conf, err := google.JWTConfigFromJSON(data, "https://www.googleapis.com/auth/bigquery")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // Initiate an http.Client. The following GET request will be
+ // authorized and authenticated on the behalf of
+ // your service account.
+ client := conf.Client(oauth2.NoContext)
+ client.Get("...")
+}
+
+func ExampleSDKConfig() {
+ // The credentials will be obtained from the first account that
+ // has been authorized with `gcloud auth login`.
+ conf, err := google.NewSDKConfig("")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // Initiate an http.Client. The following GET request will be
+ // authorized and authenticated on the behalf of the SDK user.
+ client := conf.Client(oauth2.NoContext)
+ client.Get("...")
+}
+
+func Example_serviceAccount() {
+ // Your credentials should be obtained from the Google
+ // Developer Console (https://console.developers.google.com).
+ conf := &jwt.Config{
+ Email: "xxx@developer.gserviceaccount.com",
+ // The contents of your RSA private key or your PEM file
+ // that contains a private key.
+ // If you have a p12 file instead, you
+ // can use `openssl` to export the private key into a pem file.
+ //
+ // $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes
+ //
+ // The field only supports PEM containers with no passphrase.
+ // The openssl command will convert p12 keys to passphrase-less PEM containers.
+ PrivateKey: []byte("-----BEGIN RSA PRIVATE KEY-----..."),
+ Scopes: []string{
+ "https://www.googleapis.com/auth/bigquery",
+ "https://www.googleapis.com/auth/blogger",
+ },
+ TokenURL: google.JWTTokenURL,
+ // If you would like to impersonate a user, you can
+ // create a transport with a subject. The following GET
+ // request will be made on the behalf of user@example.com.
+ // Optional.
+ Subject: "user@example.com",
+ }
+ // Initiate an http.Client, the following GET request will be
+ // authorized and authenticated on the behalf of user@example.com.
+ client := conf.Client(oauth2.NoContext)
+ client.Get("...")
+}
+
+func ExampleAppEngineTokenSource() {
+ var req *http.Request // from the ServeHTTP handler
+ ctx := appengine.NewContext(req)
+ client := &http.Client{
+ Transport: &oauth2.Transport{
+ Source: google.AppEngineTokenSource(ctx, "https://www.googleapis.com/auth/bigquery"),
+ Base: &urlfetch.Transport{
+ Context: ctx,
+ },
+ },
+ }
+ client.Get("...")
+}
+
+func ExampleComputeTokenSource() {
+ client := &http.Client{
+ Transport: &oauth2.Transport{
+ // Fetch from Google Compute Engine's metadata server to retrieve
+ // an access token for the provided account.
+ // If no account is specified, "default" is used.
+ Source: google.ComputeTokenSource(""),
+ },
+ }
+ client.Get("...")
+}
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..66a8b0e
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/google.go
@@ -0,0 +1,202 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package google provides support for making OAuth2 authorized and
+// authenticated HTTP requests to Google APIs.
+// It supports the Web server flow, client-side credentials, service accounts,
+// Google Compute Engine service accounts, and Google App Engine service
+// accounts.
+//
+// For more information, please read
+// https://developers.google.com/accounts/docs/OAuth2
+// and
+// https://developers.google.com/accounts/docs/application-default-credentials.
+package google // import "golang.org/x/oauth2/google"
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "cloud.google.com/go/compute/metadata"
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/jwt"
+)
+
+// Endpoint is Google's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://accounts.google.com/o/oauth2/auth",
+ TokenURL: "https://accounts.google.com/o/oauth2/token",
+}
+
+// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
+const JWTTokenURL = "https://accounts.google.com/o/oauth2/token"
+
+// ConfigFromJSON uses a Google Developers Console client_credentials.json
+// file to construct a config.
+// client_credentials.json can be downloaded from
+// https://console.developers.google.com, under "Credentials". Download the Web
+// application credentials in the JSON format and provide the contents of the
+// file as jsonKey.
+func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) {
+ type cred struct {
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret"`
+ RedirectURIs []string `json:"redirect_uris"`
+ AuthURI string `json:"auth_uri"`
+ TokenURI string `json:"token_uri"`
+ }
+ var j struct {
+ Web *cred `json:"web"`
+ Installed *cred `json:"installed"`
+ }
+ if err := json.Unmarshal(jsonKey, &j); err != nil {
+ return nil, err
+ }
+ var c *cred
+ switch {
+ case j.Web != nil:
+ c = j.Web
+ case j.Installed != nil:
+ c = j.Installed
+ default:
+ return nil, fmt.Errorf("oauth2/google: no credentials found")
+ }
+ if len(c.RedirectURIs) < 1 {
+ return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json")
+ }
+ return &oauth2.Config{
+ ClientID: c.ClientID,
+ ClientSecret: c.ClientSecret,
+ RedirectURL: c.RedirectURIs[0],
+ Scopes: scope,
+ Endpoint: oauth2.Endpoint{
+ AuthURL: c.AuthURI,
+ TokenURL: c.TokenURI,
+ },
+ }, nil
+}
+
+// JWTConfigFromJSON uses a Google Developers service account JSON key file to read
+// the credentials that authorize and authenticate the requests.
+// Create a service account on "Credentials" for your project at
+// https://console.developers.google.com to download a JSON key file.
+func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
+ var f credentialsFile
+ if err := json.Unmarshal(jsonKey, &f); err != nil {
+ return nil, err
+ }
+ if f.Type != serviceAccountKey {
+ return nil, fmt.Errorf("google: read JWT from JSON credentials: 'type' field is %q (expected %q)", f.Type, serviceAccountKey)
+ }
+ scope = append([]string(nil), scope...) // copy
+ return f.jwtConfig(scope), nil
+}
+
+// JSON key file types.
+const (
+ serviceAccountKey = "service_account"
+ userCredentialsKey = "authorized_user"
+)
+
+// credentialsFile is the unmarshalled representation of a credentials file.
+type credentialsFile struct {
+ Type string `json:"type"` // serviceAccountKey or userCredentialsKey
+
+ // Service Account fields
+ ClientEmail string `json:"client_email"`
+ PrivateKeyID string `json:"private_key_id"`
+ PrivateKey string `json:"private_key"`
+ TokenURL string `json:"token_uri"`
+ ProjectID string `json:"project_id"`
+
+ // User Credential fields
+ // (These typically come from gcloud auth.)
+ ClientSecret string `json:"client_secret"`
+ ClientID string `json:"client_id"`
+ RefreshToken string `json:"refresh_token"`
+}
+
+func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config {
+ cfg := &jwt.Config{
+ Email: f.ClientEmail,
+ PrivateKey: []byte(f.PrivateKey),
+ PrivateKeyID: f.PrivateKeyID,
+ Scopes: scopes,
+ TokenURL: f.TokenURL,
+ }
+ if cfg.TokenURL == "" {
+ cfg.TokenURL = JWTTokenURL
+ }
+ return cfg
+}
+
+func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oauth2.TokenSource, error) {
+ switch f.Type {
+ case serviceAccountKey:
+ cfg := f.jwtConfig(scopes)
+ return cfg.TokenSource(ctx), nil
+ case userCredentialsKey:
+ cfg := &oauth2.Config{
+ ClientID: f.ClientID,
+ ClientSecret: f.ClientSecret,
+ Scopes: scopes,
+ Endpoint: Endpoint,
+ }
+ tok := &oauth2.Token{RefreshToken: f.RefreshToken}
+ return cfg.TokenSource(ctx, tok), nil
+ case "":
+ return nil, errors.New("missing 'type' field in credentials")
+ default:
+ return nil, fmt.Errorf("unknown credential type: %q", f.Type)
+ }
+}
+
+// ComputeTokenSource returns a token source that fetches access tokens
+// from Google Compute Engine (GCE)'s metadata server. It's only valid to use
+// this token source if your program is running on a GCE instance.
+// If no account is specified, "default" is used.
+// Further information about retrieving access tokens from the GCE metadata
+// server can be found at https://cloud.google.com/compute/docs/authentication.
+func ComputeTokenSource(account string) oauth2.TokenSource {
+ return oauth2.ReuseTokenSource(nil, computeSource{account: account})
+}
+
+type computeSource struct {
+ account string
+}
+
+func (cs computeSource) Token() (*oauth2.Token, error) {
+ if !metadata.OnGCE() {
+ return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE")
+ }
+ acct := cs.account
+ if acct == "" {
+ acct = "default"
+ }
+ tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token")
+ if err != nil {
+ return nil, err
+ }
+ var res struct {
+ AccessToken string `json:"access_token"`
+ ExpiresInSec int `json:"expires_in"`
+ TokenType string `json:"token_type"`
+ }
+ err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
+ }
+ if res.ExpiresInSec == 0 || res.AccessToken == "" {
+ return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
+ }
+ return &oauth2.Token{
+ AccessToken: res.AccessToken,
+ TokenType: res.TokenType,
+ Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
+ }, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/google_test.go b/vendor/golang.org/x/oauth2/google/google_test.go
new file mode 100644
index 0000000..287c699
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/google_test.go
@@ -0,0 +1,116 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "strings"
+ "testing"
+)
+
+var webJSONKey = []byte(`
+{
+ "web": {
+ "auth_uri": "https://google.com/o/oauth2/auth",
+ "client_secret": "3Oknc4jS_wA2r9i",
+ "token_uri": "https://google.com/o/oauth2/token",
+ "client_email": "222-nprqovg5k43uum874cs9osjt2koe97g8@developer.gserviceaccount.com",
+ "redirect_uris": ["https://www.example.com/oauth2callback"],
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/222-nprqovg5k43uum874cs9osjt2koe97g8@developer.gserviceaccount.com",
+ "client_id": "222-nprqovg5k43uum874cs9osjt2koe97g8.apps.googleusercontent.com",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "javascript_origins": ["https://www.example.com"]
+ }
+}`)
+
+var installedJSONKey = []byte(`{
+ "installed": {
+ "client_id": "222-installed.apps.googleusercontent.com",
+ "redirect_uris": ["https://www.example.com/oauth2callback"]
+ }
+}`)
+
+var jwtJSONKey = []byte(`{
+ "private_key_id": "268f54e43a1af97cfc71731688434f45aca15c8b",
+ "private_key": "super secret key",
+ "client_email": "gopher@developer.gserviceaccount.com",
+ "client_id": "gopher.apps.googleusercontent.com",
+ "token_uri": "https://accounts.google.com/o/gophers/token",
+ "type": "service_account"
+}`)
+
+var jwtJSONKeyNoTokenURL = []byte(`{
+ "private_key_id": "268f54e43a1af97cfc71731688434f45aca15c8b",
+ "private_key": "super secret key",
+ "client_email": "gopher@developer.gserviceaccount.com",
+ "client_id": "gopher.apps.googleusercontent.com",
+ "type": "service_account"
+}`)
+
+func TestConfigFromJSON(t *testing.T) {
+ conf, err := ConfigFromJSON(webJSONKey, "scope1", "scope2")
+ if err != nil {
+ t.Error(err)
+ }
+ if got, want := conf.ClientID, "222-nprqovg5k43uum874cs9osjt2koe97g8.apps.googleusercontent.com"; got != want {
+ t.Errorf("ClientID = %q; want %q", got, want)
+ }
+ if got, want := conf.ClientSecret, "3Oknc4jS_wA2r9i"; got != want {
+ t.Errorf("ClientSecret = %q; want %q", got, want)
+ }
+ if got, want := conf.RedirectURL, "https://www.example.com/oauth2callback"; got != want {
+ t.Errorf("RedictURL = %q; want %q", got, want)
+ }
+ if got, want := strings.Join(conf.Scopes, ","), "scope1,scope2"; got != want {
+ t.Errorf("Scopes = %q; want %q", got, want)
+ }
+ if got, want := conf.Endpoint.AuthURL, "https://google.com/o/oauth2/auth"; got != want {
+ t.Errorf("AuthURL = %q; want %q", got, want)
+ }
+ if got, want := conf.Endpoint.TokenURL, "https://google.com/o/oauth2/token"; got != want {
+ t.Errorf("TokenURL = %q; want %q", got, want)
+ }
+}
+
+func TestConfigFromJSON_Installed(t *testing.T) {
+ conf, err := ConfigFromJSON(installedJSONKey)
+ if err != nil {
+ t.Error(err)
+ }
+ if got, want := conf.ClientID, "222-installed.apps.googleusercontent.com"; got != want {
+ t.Errorf("ClientID = %q; want %q", got, want)
+ }
+}
+
+func TestJWTConfigFromJSON(t *testing.T) {
+ conf, err := JWTConfigFromJSON(jwtJSONKey, "scope1", "scope2")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got, want := conf.Email, "gopher@developer.gserviceaccount.com"; got != want {
+ t.Errorf("Email = %q, want %q", got, want)
+ }
+ if got, want := string(conf.PrivateKey), "super secret key"; got != want {
+ t.Errorf("PrivateKey = %q, want %q", got, want)
+ }
+ if got, want := conf.PrivateKeyID, "268f54e43a1af97cfc71731688434f45aca15c8b"; got != want {
+ t.Errorf("PrivateKeyID = %q, want %q", got, want)
+ }
+ if got, want := strings.Join(conf.Scopes, ","), "scope1,scope2"; got != want {
+ t.Errorf("Scopes = %q; want %q", got, want)
+ }
+ if got, want := conf.TokenURL, "https://accounts.google.com/o/gophers/token"; got != want {
+ t.Errorf("TokenURL = %q; want %q", got, want)
+ }
+}
+
+func TestJWTConfigFromJSONNoTokenURL(t *testing.T) {
+ conf, err := JWTConfigFromJSON(jwtJSONKeyNoTokenURL, "scope1", "scope2")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got, want := conf.TokenURL, "https://accounts.google.com/o/oauth2/token"; got != want {
+ t.Errorf("TokenURL = %q; want %q", got, want)
+ }
+}
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 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "crypto/rsa"
+ "fmt"
+ "time"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+ "golang.org/x/oauth2/jws"
+)
+
+// JWTAccessTokenSourceFromJSON uses a Google Developers service account JSON
+// key file to read the credentials that authorize and authenticate the
+// requests, and returns a TokenSource that does not use any OAuth2 flow but
+// instead creates a JWT and sends that as the access token.
+// The audience is typically a URL that specifies the scope of the credentials.
+//
+// Note that this is not a standard OAuth flow, but rather an
+// optimization supported by a few Google services.
+// Unless you know otherwise, you should use JWTConfigFromJSON instead.
+func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.TokenSource, error) {
+ cfg, err := JWTConfigFromJSON(jsonKey)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not parse JSON key: %v", err)
+ }
+ pk, err := internal.ParseKey(cfg.PrivateKey)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not parse key: %v", err)
+ }
+ ts := &jwtAccessTokenSource{
+ email: cfg.Email,
+ audience: audience,
+ pk: pk,
+ pkID: cfg.PrivateKeyID,
+ }
+ tok, err := ts.Token()
+ if err != nil {
+ return nil, err
+ }
+ return oauth2.ReuseTokenSource(tok, ts), nil
+}
+
+type jwtAccessTokenSource struct {
+ email, audience string
+ pk *rsa.PrivateKey
+ pkID string
+}
+
+func (ts *jwtAccessTokenSource) Token() (*oauth2.Token, error) {
+ iat := time.Now()
+ exp := iat.Add(time.Hour)
+ cs := &jws.ClaimSet{
+ Iss: ts.email,
+ Sub: ts.email,
+ Aud: ts.audience,
+ Iat: iat.Unix(),
+ Exp: exp.Unix(),
+ }
+ hdr := &jws.Header{
+ Algorithm: "RS256",
+ Typ: "JWT",
+ KeyID: string(ts.pkID),
+ }
+ msg, err := jws.Encode(hdr, cs, ts.pk)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not encode JWT: %v", err)
+ }
+ return &oauth2.Token{AccessToken: msg, TokenType: "Bearer", Expiry: exp}, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/jwt_test.go b/vendor/golang.org/x/oauth2/google/jwt_test.go
new file mode 100644
index 0000000..f844436
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/jwt_test.go
@@ -0,0 +1,91 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/json"
+ "encoding/pem"
+ "strings"
+ "testing"
+ "time"
+
+ "golang.org/x/oauth2/jws"
+)
+
+func TestJWTAccessTokenSourceFromJSON(t *testing.T) {
+ // Generate a key we can use in the test data.
+ privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Encode the key and substitute into our example JSON.
+ enc := pem.EncodeToMemory(&pem.Block{
+ Type: "PRIVATE KEY",
+ Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
+ })
+ enc, err = json.Marshal(string(enc))
+ if err != nil {
+ t.Fatalf("json.Marshal: %v", err)
+ }
+ jsonKey := bytes.Replace(jwtJSONKey, []byte(`"super secret key"`), enc, 1)
+
+ ts, err := JWTAccessTokenSourceFromJSON(jsonKey, "audience")
+ if err != nil {
+ t.Fatalf("JWTAccessTokenSourceFromJSON: %v\nJSON: %s", err, string(jsonKey))
+ }
+
+ tok, err := ts.Token()
+ if err != nil {
+ t.Fatalf("Token: %v", err)
+ }
+
+ if got, want := tok.TokenType, "Bearer"; got != want {
+ t.Errorf("TokenType = %q, want %q", got, want)
+ }
+ if got := tok.Expiry; tok.Expiry.Before(time.Now()) {
+ t.Errorf("Expiry = %v, should not be expired", got)
+ }
+
+ err = jws.Verify(tok.AccessToken, &privateKey.PublicKey)
+ if err != nil {
+ t.Errorf("jws.Verify on AccessToken: %v", err)
+ }
+
+ claim, err := jws.Decode(tok.AccessToken)
+ if err != nil {
+ t.Fatalf("jws.Decode on AccessToken: %v", err)
+ }
+
+ if got, want := claim.Iss, "gopher@developer.gserviceaccount.com"; got != want {
+ t.Errorf("Iss = %q, want %q", got, want)
+ }
+ if got, want := claim.Sub, "gopher@developer.gserviceaccount.com"; got != want {
+ t.Errorf("Sub = %q, want %q", got, want)
+ }
+ if got, want := claim.Aud, "audience"; got != want {
+ t.Errorf("Aud = %q, want %q", got, want)
+ }
+
+ // Finally, check the header private key.
+ parts := strings.Split(tok.AccessToken, ".")
+ hdrJSON, err := base64.RawURLEncoding.DecodeString(parts[0])
+ if err != nil {
+ t.Fatalf("base64 DecodeString: %v\nString: %q", err, parts[0])
+ }
+ var hdr jws.Header
+ if err := json.Unmarshal([]byte(hdrJSON), &hdr); err != nil {
+ t.Fatalf("json.Unmarshal: %v (%q)", err, hdrJSON)
+ }
+
+ if got, want := hdr.KeyID, "268f54e43a1af97cfc71731688434f45aca15c8b"; got != want {
+ t.Errorf("Header KeyID = %q, want %q", got, want)
+ }
+}
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..bdc1808
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/sdk.go
@@ -0,0 +1,172 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "os"
+ "os/user"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+)
+
+type sdkCredentials struct {
+ Data []struct {
+ Credential struct {
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret"`
+ AccessToken string `json:"access_token"`
+ RefreshToken string `json:"refresh_token"`
+ TokenExpiry *time.Time `json:"token_expiry"`
+ } `json:"credential"`
+ Key struct {
+ Account string `json:"account"`
+ Scope string `json:"scope"`
+ } `json:"key"`
+ }
+}
+
+// An SDKConfig provides access to tokens from an account already
+// authorized via the Google Cloud SDK.
+type SDKConfig struct {
+ conf oauth2.Config
+ initialToken *oauth2.Token
+}
+
+// NewSDKConfig creates an SDKConfig for the given Google Cloud SDK
+// account. If account is empty, the account currently active in
+// Google Cloud SDK properties is used.
+// Google Cloud SDK credentials must be created by running `gcloud auth`
+// before using this function.
+// The Google Cloud SDK is available at https://cloud.google.com/sdk/.
+func NewSDKConfig(account string) (*SDKConfig, error) {
+ configPath, err := sdkConfigPath()
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: error getting SDK config path: %v", err)
+ }
+ credentialsPath := filepath.Join(configPath, "credentials")
+ f, err := os.Open(credentialsPath)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to load SDK credentials: %v", err)
+ }
+ defer f.Close()
+
+ var c sdkCredentials
+ if err := json.NewDecoder(f).Decode(&c); err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to decode SDK credentials from %q: %v", credentialsPath, err)
+ }
+ if len(c.Data) == 0 {
+ return nil, fmt.Errorf("oauth2/google: no credentials found in %q, run `gcloud auth login` to create one", credentialsPath)
+ }
+ if account == "" {
+ propertiesPath := filepath.Join(configPath, "properties")
+ f, err := os.Open(propertiesPath)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to load SDK properties: %v", err)
+ }
+ defer f.Close()
+ ini, err := internal.ParseINI(f)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to parse SDK properties %q: %v", propertiesPath, err)
+ }
+ core, ok := ini["core"]
+ if !ok {
+ return nil, fmt.Errorf("oauth2/google: failed to find [core] section in %v", ini)
+ }
+ active, ok := core["account"]
+ if !ok {
+ return nil, fmt.Errorf("oauth2/google: failed to find %q attribute in %v", "account", core)
+ }
+ account = active
+ }
+
+ for _, d := range c.Data {
+ if account == "" || d.Key.Account == account {
+ if d.Credential.AccessToken == "" && d.Credential.RefreshToken == "" {
+ return nil, fmt.Errorf("oauth2/google: no token available for account %q", account)
+ }
+ var expiry time.Time
+ if d.Credential.TokenExpiry != nil {
+ expiry = *d.Credential.TokenExpiry
+ }
+ return &SDKConfig{
+ conf: oauth2.Config{
+ ClientID: d.Credential.ClientID,
+ ClientSecret: d.Credential.ClientSecret,
+ Scopes: strings.Split(d.Key.Scope, " "),
+ Endpoint: Endpoint,
+ RedirectURL: "oob",
+ },
+ initialToken: &oauth2.Token{
+ AccessToken: d.Credential.AccessToken,
+ RefreshToken: d.Credential.RefreshToken,
+ Expiry: expiry,
+ },
+ }, nil
+ }
+ }
+ return nil, fmt.Errorf("oauth2/google: no such credentials for account %q", account)
+}
+
+// Client returns an HTTP client using Google Cloud SDK credentials to
+// authorize requests. The token will auto-refresh as necessary. The
+// underlying http.RoundTripper will be obtained using the provided
+// context. The returned client and its Transport should not be
+// modified.
+func (c *SDKConfig) Client(ctx context.Context) *http.Client {
+ return &http.Client{
+ Transport: &oauth2.Transport{
+ Source: c.TokenSource(ctx),
+ },
+ }
+}
+
+// TokenSource returns an oauth2.TokenSource that retrieve tokens from
+// Google Cloud SDK credentials using the provided context.
+// It will returns the current access token stored in the credentials,
+// and refresh it when it expires, but it won't update the credentials
+// with the new access token.
+func (c *SDKConfig) TokenSource(ctx context.Context) oauth2.TokenSource {
+ return c.conf.TokenSource(ctx, c.initialToken)
+}
+
+// Scopes are the OAuth 2.0 scopes the current account is authorized for.
+func (c *SDKConfig) Scopes() []string {
+ return c.conf.Scopes
+}
+
+// sdkConfigPath tries to guess where the gcloud config is located.
+// It can be overridden during tests.
+var sdkConfigPath = func() (string, error) {
+ if runtime.GOOS == "windows" {
+ return filepath.Join(os.Getenv("APPDATA"), "gcloud"), nil
+ }
+ homeDir := guessUnixHomeDir()
+ if homeDir == "" {
+ return "", errors.New("unable to get current user home directory: os/user lookup failed; $HOME is empty")
+ }
+ return filepath.Join(homeDir, ".config", "gcloud"), nil
+}
+
+func guessUnixHomeDir() string {
+ // Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470
+ if v := os.Getenv("HOME"); v != "" {
+ return v
+ }
+ // Else, fall back to user.Current:
+ if u, err := user.Current(); err == nil {
+ return u.HomeDir
+ }
+ return ""
+}
diff --git a/vendor/golang.org/x/oauth2/google/sdk_test.go b/vendor/golang.org/x/oauth2/google/sdk_test.go
new file mode 100644
index 0000000..4489bb9
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/sdk_test.go
@@ -0,0 +1,46 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import "testing"
+
+func TestSDKConfig(t *testing.T) {
+ sdkConfigPath = func() (string, error) {
+ return "testdata/gcloud", nil
+ }
+
+ tests := []struct {
+ account string
+ accessToken string
+ err bool
+ }{
+ {"", "bar_access_token", false},
+ {"foo@example.com", "foo_access_token", false},
+ {"bar@example.com", "bar_access_token", false},
+ {"baz@serviceaccount.example.com", "", true},
+ }
+ for _, tt := range tests {
+ c, err := NewSDKConfig(tt.account)
+ if got, want := err != nil, tt.err; got != want {
+ if !tt.err {
+ t.Errorf("got %v, want nil", err)
+ } else {
+ t.Errorf("got nil, want error")
+ }
+ continue
+ }
+ if err != nil {
+ continue
+ }
+ tok := c.initialToken
+ if tok == nil {
+ t.Errorf("got nil, want %q", tt.accessToken)
+ continue
+ }
+ if tok.AccessToken != tt.accessToken {
+ t.Errorf("got %q, want %q", tok.AccessToken, tt.accessToken)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/google/testdata/gcloud/credentials b/vendor/golang.org/x/oauth2/google/testdata/gcloud/credentials
new file mode 100644
index 0000000..ff5eefb
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/testdata/gcloud/credentials
@@ -0,0 +1,122 @@
+{
+ "data": [
+ {
+ "credential": {
+ "_class": "OAuth2Credentials",
+ "_module": "oauth2client.client",
+ "access_token": "foo_access_token",
+ "client_id": "foo_client_id",
+ "client_secret": "foo_client_secret",
+ "id_token": {
+ "at_hash": "foo_at_hash",
+ "aud": "foo_aud",
+ "azp": "foo_azp",
+ "cid": "foo_cid",
+ "email": "foo@example.com",
+ "email_verified": true,
+ "exp": 1420573614,
+ "iat": 1420569714,
+ "id": "1337",
+ "iss": "accounts.google.com",
+ "sub": "1337",
+ "token_hash": "foo_token_hash",
+ "verified_email": true
+ },
+ "invalid": false,
+ "refresh_token": "foo_refresh_token",
+ "revoke_uri": "https://accounts.google.com/o/oauth2/revoke",
+ "token_expiry": "2015-01-09T00:51:51Z",
+ "token_response": {
+ "access_token": "foo_access_token",
+ "expires_in": 3600,
+ "id_token": "foo_id_token",
+ "token_type": "Bearer"
+ },
+ "token_uri": "https://accounts.google.com/o/oauth2/token",
+ "user_agent": "Cloud SDK Command Line Tool"
+ },
+ "key": {
+ "account": "foo@example.com",
+ "clientId": "foo_client_id",
+ "scope": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/ndev.cloudman https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/sqlservice.admin https://www.googleapis.com/auth/prediction https://www.googleapis.com/auth/projecthosting",
+ "type": "google-cloud-sdk"
+ }
+ },
+ {
+ "credential": {
+ "_class": "OAuth2Credentials",
+ "_module": "oauth2client.client",
+ "access_token": "bar_access_token",
+ "client_id": "bar_client_id",
+ "client_secret": "bar_client_secret",
+ "id_token": {
+ "at_hash": "bar_at_hash",
+ "aud": "bar_aud",
+ "azp": "bar_azp",
+ "cid": "bar_cid",
+ "email": "bar@example.com",
+ "email_verified": true,
+ "exp": 1420573614,
+ "iat": 1420569714,
+ "id": "1337",
+ "iss": "accounts.google.com",
+ "sub": "1337",
+ "token_hash": "bar_token_hash",
+ "verified_email": true
+ },
+ "invalid": false,
+ "refresh_token": "bar_refresh_token",
+ "revoke_uri": "https://accounts.google.com/o/oauth2/revoke",
+ "token_expiry": "2015-01-09T00:51:51Z",
+ "token_response": {
+ "access_token": "bar_access_token",
+ "expires_in": 3600,
+ "id_token": "bar_id_token",
+ "token_type": "Bearer"
+ },
+ "token_uri": "https://accounts.google.com/o/oauth2/token",
+ "user_agent": "Cloud SDK Command Line Tool"
+ },
+ "key": {
+ "account": "bar@example.com",
+ "clientId": "bar_client_id",
+ "scope": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/ndev.cloudman https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/sqlservice.admin https://www.googleapis.com/auth/prediction https://www.googleapis.com/auth/projecthosting",
+ "type": "google-cloud-sdk"
+ }
+ },
+ {
+ "credential": {
+ "_class": "ServiceAccountCredentials",
+ "_kwargs": {},
+ "_module": "oauth2client.client",
+ "_private_key_id": "00000000000000000000000000000000",
+ "_private_key_pkcs8_text": "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQCt3fpiynPSaUhWSIKMGV331zudwJ6GkGmvQtwsoK2S2LbvnSwU\nNxgj4fp08kIDR5p26wF4+t/HrKydMwzftXBfZ9UmLVJgRdSswmS5SmChCrfDS5OE\nvFFcN5+6w1w8/Nu657PF/dse8T0bV95YrqyoR0Osy8WHrUOMSIIbC3hRuwIDAQAB\nAoGAJrGE/KFjn0sQ7yrZ6sXmdLawrM3mObo/2uI9T60+k7SpGbBX0/Pi6nFrJMWZ\nTVONG7P3Mu5aCPzzuVRYJB0j8aldSfzABTY3HKoWCczqw1OztJiEseXGiYz4QOyr\nYU3qDyEpdhS6q6wcoLKGH+hqRmz6pcSEsc8XzOOu7s4xW8kCQQDkc75HjhbarCnd\nJJGMe3U76+6UGmdK67ltZj6k6xoB5WbTNChY9TAyI2JC+ppYV89zv3ssj4L+02u3\nHIHFGxsHAkEAwtU1qYb1tScpchPobnYUFiVKJ7KA8EZaHVaJJODW/cghTCV7BxcJ\nbgVvlmk4lFKn3lPKAgWw7PdQsBTVBUcCrQJATPwoIirizrv3u5soJUQxZIkENAqV\nxmybZx9uetrzP7JTrVbFRf0SScMcyN90hdLJiQL8+i4+gaszgFht7sNMnwJAAbfj\nq0UXcauQwALQ7/h2oONfTg5S+MuGC/AxcXPSMZbMRGGoPh3D5YaCv27aIuS/ukQ+\n6dmm/9AGlCb64fsIWQJAPaokbjIifo+LwC5gyK73Mc4t8nAOSZDenzd/2f6TCq76\nS1dcnKiPxaED7W/y6LJiuBT2rbZiQ2L93NJpFZD/UA==\n-----END RSA PRIVATE KEY-----\n",
+ "_revoke_uri": "https://accounts.google.com/o/oauth2/revoke",
+ "_scopes": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/ndev.cloudman https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/sqlservice.admin https://www.googleapis.com/auth/prediction https://www.googleapis.com/auth/projecthosting",
+ "_service_account_email": "baz@serviceaccount.example.com",
+ "_service_account_id": "baz.serviceaccount.example.com",
+ "_token_uri": "https://accounts.google.com/o/oauth2/token",
+ "_user_agent": "Cloud SDK Command Line Tool",
+ "access_token": null,
+ "assertion_type": null,
+ "client_id": null,
+ "client_secret": null,
+ "id_token": null,
+ "invalid": false,
+ "refresh_token": null,
+ "revoke_uri": "https://accounts.google.com/o/oauth2/revoke",
+ "service_account_name": "baz@serviceaccount.example.com",
+ "token_expiry": null,
+ "token_response": null,
+ "user_agent": "Cloud SDK Command Line Tool"
+ },
+ "key": {
+ "account": "baz@serviceaccount.example.com",
+ "clientId": "baz_client_id",
+ "scope": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/ndev.cloudman https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/sqlservice.admin https://www.googleapis.com/auth/prediction https://www.googleapis.com/auth/projecthosting",
+ "type": "google-cloud-sdk"
+ }
+ }
+ ],
+ "file_version": 1
+}
diff --git a/vendor/golang.org/x/oauth2/google/testdata/gcloud/properties b/vendor/golang.org/x/oauth2/google/testdata/gcloud/properties
new file mode 100644
index 0000000..025de88
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/testdata/gcloud/properties
@@ -0,0 +1,2 @@
+[core]
+account = bar@example.com \ No newline at end of file
diff --git a/vendor/golang.org/x/oauth2/heroku/heroku.go b/vendor/golang.org/x/oauth2/heroku/heroku.go
new file mode 100644
index 0000000..5b4fdb8
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/heroku/heroku.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package heroku provides constants for using OAuth2 to access Heroku.
+package heroku // import "golang.org/x/oauth2/heroku"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Heroku's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://id.heroku.com/oauth/authorize",
+ TokenURL: "https://id.heroku.com/oauth/token",
+}
diff --git a/vendor/golang.org/x/oauth2/hipchat/hipchat.go b/vendor/golang.org/x/oauth2/hipchat/hipchat.go
new file mode 100644
index 0000000..594fe07
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/hipchat/hipchat.go
@@ -0,0 +1,60 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package hipchat provides constants for using OAuth2 to access HipChat.
+package hipchat // import "golang.org/x/oauth2/hipchat"
+
+import (
+ "encoding/json"
+ "errors"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/clientcredentials"
+)
+
+// Endpoint is HipChat's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.hipchat.com/users/authorize",
+ TokenURL: "https://api.hipchat.com/v2/oauth/token",
+}
+
+// ServerEndpoint returns a new oauth2.Endpoint for a HipChat Server instance
+// running on the given domain or host.
+func ServerEndpoint(host string) oauth2.Endpoint {
+ return oauth2.Endpoint{
+ AuthURL: "https://" + host + "/users/authorize",
+ TokenURL: "https://" + host + "/v2/oauth/token",
+ }
+}
+
+// ClientCredentialsConfigFromCaps generates a Config from a HipChat API
+// capabilities descriptor. It does not verify the scopes against the
+// capabilities document at this time.
+//
+// For more information see: https://www.hipchat.com/docs/apiv2/method/get_capabilities
+func ClientCredentialsConfigFromCaps(capsJSON []byte, clientID, clientSecret string, scopes ...string) (*clientcredentials.Config, error) {
+ var caps struct {
+ Caps struct {
+ Endpoint struct {
+ TokenURL string `json:"tokenUrl"`
+ } `json:"oauth2Provider"`
+ } `json:"capabilities"`
+ }
+
+ if err := json.Unmarshal(capsJSON, &caps); err != nil {
+ return nil, err
+ }
+
+ // Verify required fields.
+ if caps.Caps.Endpoint.TokenURL == "" {
+ return nil, errors.New("oauth2/hipchat: missing OAuth2 token URL in the capabilities descriptor JSON")
+ }
+
+ return &clientcredentials.Config{
+ ClientID: clientID,
+ ClientSecret: clientSecret,
+ Scopes: scopes,
+ TokenURL: caps.Caps.Endpoint.TokenURL,
+ }, nil
+}
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 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package internal contains support packages for oauth2 package.
+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..6978192
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/oauth2.go
@@ -0,0 +1,75 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "bufio"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// ParseKey converts the binary contents of a private key file
+// to an *rsa.PrivateKey. It detects whether the private key is in a
+// PEM container or not. If so, it extracts the the private key
+// from PEM container before conversion. It only supports PEM
+// containers with no passphrase.
+func ParseKey(key []byte) (*rsa.PrivateKey, error) {
+ block, _ := pem.Decode(key)
+ if block != nil {
+ key = block.Bytes
+ }
+ parsedKey, err := x509.ParsePKCS8PrivateKey(key)
+ if err != nil {
+ parsedKey, err = x509.ParsePKCS1PrivateKey(key)
+ if err != nil {
+ return nil, fmt.Errorf("private key should be a PEM or plain PKSC1 or PKCS8; parse error: %v", err)
+ }
+ }
+ parsed, ok := parsedKey.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("private key is invalid")
+ }
+ return parsed, nil
+}
+
+func ParseINI(ini io.Reader) (map[string]map[string]string, error) {
+ result := map[string]map[string]string{
+ "": {}, // root section
+ }
+ scanner := bufio.NewScanner(ini)
+ currentSection := ""
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+ if strings.HasPrefix(line, ";") {
+ // comment.
+ continue
+ }
+ if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
+ currentSection = strings.TrimSpace(line[1 : len(line)-1])
+ result[currentSection] = map[string]string{}
+ continue
+ }
+ parts := strings.SplitN(line, "=", 2)
+ if len(parts) == 2 && parts[0] != "" {
+ result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("error scanning ini: %v", err)
+ }
+ return result, nil
+}
+
+func CondVal(v string) []string {
+ if v == "" {
+ return nil
+ }
+ return []string{v}
+}
diff --git a/vendor/golang.org/x/oauth2/internal/oauth2_test.go b/vendor/golang.org/x/oauth2/internal/oauth2_test.go
new file mode 100644
index 0000000..07d51c4
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/oauth2_test.go
@@ -0,0 +1,61 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestParseINI(t *testing.T) {
+ tests := []struct {
+ ini string
+ want map[string]map[string]string
+ }{
+ {
+ `root = toor
+[foo]
+bar = hop
+ini = nin
+`,
+ map[string]map[string]string{
+ "": {"root": "toor"},
+ "foo": {"bar": "hop", "ini": "nin"},
+ },
+ },
+ {
+ `[empty]
+[section]
+empty=
+`,
+ map[string]map[string]string{
+ "": {},
+ "empty": {},
+ "section": {"empty": ""},
+ },
+ },
+ {
+ `ignore
+[invalid
+=stuff
+;comment=true
+`,
+ map[string]map[string]string{
+ "": {},
+ },
+ },
+ }
+ for _, tt := range tests {
+ result, err := ParseINI(strings.NewReader(tt.ini))
+ if err != nil {
+ t.Errorf("ParseINI(%q) error %v, want: no error", tt.ini, err)
+ continue
+ }
+ if !reflect.DeepEqual(result, tt.want) {
+ t.Errorf("ParseINI(%q) = %#v, want: %#v", tt.ini, result, tt.want)
+ }
+ }
+}
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..600dbe6
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/token.go
@@ -0,0 +1,251 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "mime"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/net/context/ctxhttp"
+)
+
+// Token represents the credentials used to authorize
+// the requests to access protected resources on the OAuth 2.0
+// provider's backend.
+//
+// This type is a mirror of oauth2.Token and exists to break
+// an otherwise-circular dependency. Other internal packages
+// should convert this Token into an oauth2.Token before use.
+type Token struct {
+ // AccessToken is the token that authorizes and authenticates
+ // the requests.
+ AccessToken string
+
+ // TokenType is the type of token.
+ // The Type method returns either this or "Bearer", the default.
+ TokenType string
+
+ // RefreshToken is a token that's used by the application
+ // (as opposed to the user) to refresh the access token
+ // if it expires.
+ RefreshToken string
+
+ // Expiry is the optional expiration time of the access token.
+ //
+ // If zero, TokenSource implementations will reuse the same
+ // token forever and RefreshToken or equivalent
+ // mechanisms for that TokenSource will not be used.
+ Expiry time.Time
+
+ // Raw optionally contains extra metadata from the server
+ // when updating a token.
+ Raw interface{}
+}
+
+// tokenJSON is the struct representing the HTTP response from OAuth2
+// providers returning a token in JSON form.
+type tokenJSON struct {
+ AccessToken string `json:"access_token"`
+ TokenType string `json:"token_type"`
+ RefreshToken string `json:"refresh_token"`
+ ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
+ Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in
+}
+
+func (e *tokenJSON) expiry() (t time.Time) {
+ if v := e.ExpiresIn; v != 0 {
+ return time.Now().Add(time.Duration(v) * time.Second)
+ }
+ if v := e.Expires; v != 0 {
+ return time.Now().Add(time.Duration(v) * time.Second)
+ }
+ return
+}
+
+type expirationTime int32
+
+func (e *expirationTime) UnmarshalJSON(b []byte) error {
+ var n json.Number
+ err := json.Unmarshal(b, &n)
+ if err != nil {
+ return err
+ }
+ i, err := n.Int64()
+ if err != nil {
+ return err
+ }
+ *e = expirationTime(i)
+ return nil
+}
+
+var brokenAuthHeaderProviders = []string{
+ "https://accounts.google.com/",
+ "https://api.codeswholesale.com/oauth/token",
+ "https://api.dropbox.com/",
+ "https://api.dropboxapi.com/",
+ "https://api.instagram.com/",
+ "https://api.netatmo.net/",
+ "https://api.odnoklassniki.ru/",
+ "https://api.pushbullet.com/",
+ "https://api.soundcloud.com/",
+ "https://api.twitch.tv/",
+ "https://app.box.com/",
+ "https://connect.stripe.com/",
+ "https://graph.facebook.com", // see https://github.com/golang/oauth2/issues/214
+ "https://login.microsoftonline.com/",
+ "https://login.salesforce.com/",
+ "https://login.windows.net",
+ "https://login.live.com/",
+ "https://oauth.sandbox.trainingpeaks.com/",
+ "https://oauth.trainingpeaks.com/",
+ "https://oauth.vk.com/",
+ "https://openapi.baidu.com/",
+ "https://slack.com/",
+ "https://test-sandbox.auth.corp.google.com",
+ "https://test.salesforce.com/",
+ "https://user.gini.net/",
+ "https://www.douban.com/",
+ "https://www.googleapis.com/",
+ "https://www.linkedin.com/",
+ "https://www.strava.com/oauth/",
+ "https://www.wunderlist.com/oauth/",
+ "https://api.patreon.com/",
+ "https://sandbox.codeswholesale.com/oauth/token",
+ "https://api.sipgate.com/v1/authorization/oauth",
+}
+
+// brokenAuthHeaderDomains lists broken providers that issue dynamic endpoints.
+var brokenAuthHeaderDomains = []string{
+ ".force.com",
+ ".myshopify.com",
+ ".okta.com",
+ ".oktapreview.com",
+}
+
+func RegisterBrokenAuthHeaderProvider(tokenURL string) {
+ brokenAuthHeaderProviders = append(brokenAuthHeaderProviders, tokenURL)
+}
+
+// providerAuthHeaderWorks reports whether the OAuth2 server identified by the tokenURL
+// implements the OAuth2 spec correctly
+// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
+// In summary:
+// - Reddit only accepts client secret in the Authorization header
+// - Dropbox accepts either it in URL param or Auth header, but not both.
+// - Google only accepts URL param (not spec compliant?), not Auth header
+// - Stripe only accepts client secret in Auth header with Bearer method, not Basic
+func providerAuthHeaderWorks(tokenURL string) bool {
+ for _, s := range brokenAuthHeaderProviders {
+ if strings.HasPrefix(tokenURL, s) {
+ // Some sites fail to implement the OAuth2 spec fully.
+ return false
+ }
+ }
+
+ if u, err := url.Parse(tokenURL); err == nil {
+ for _, s := range brokenAuthHeaderDomains {
+ if strings.HasSuffix(u.Host, s) {
+ return false
+ }
+ }
+ }
+
+ // Assume the provider implements the spec properly
+ // otherwise. We can add more exceptions as they're
+ // discovered. We will _not_ be adding configurable hooks
+ // to this package to let users select server bugs.
+ return true
+}
+
+func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values) (*Token, error) {
+ hc, err := ContextClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ bustedAuth := !providerAuthHeaderWorks(tokenURL)
+ if bustedAuth {
+ if clientID != "" {
+ v.Set("client_id", clientID)
+ }
+ if clientSecret != "" {
+ v.Set("client_secret", clientSecret)
+ }
+ }
+ req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode()))
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ if !bustedAuth {
+ req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret))
+ }
+ r, err := ctxhttp.Do(ctx, hc, req)
+ if err != nil {
+ return nil, err
+ }
+ defer r.Body.Close()
+ body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20))
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ if code := r.StatusCode; code < 200 || code > 299 {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", r.Status, body)
+ }
+
+ var token *Token
+ content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
+ switch content {
+ case "application/x-www-form-urlencoded", "text/plain":
+ vals, err := url.ParseQuery(string(body))
+ if err != nil {
+ return nil, err
+ }
+ token = &Token{
+ AccessToken: vals.Get("access_token"),
+ TokenType: vals.Get("token_type"),
+ RefreshToken: vals.Get("refresh_token"),
+ Raw: vals,
+ }
+ e := vals.Get("expires_in")
+ if e == "" {
+ // TODO(jbd): Facebook's OAuth2 implementation is broken and
+ // returns expires_in field in expires. Remove the fallback to expires,
+ // when Facebook fixes their implementation.
+ e = vals.Get("expires")
+ }
+ expires, _ := strconv.Atoi(e)
+ if expires != 0 {
+ token.Expiry = time.Now().Add(time.Duration(expires) * time.Second)
+ }
+ default:
+ var tj tokenJSON
+ if err = json.Unmarshal(body, &tj); err != nil {
+ return nil, err
+ }
+ token = &Token{
+ AccessToken: tj.AccessToken,
+ TokenType: tj.TokenType,
+ RefreshToken: tj.RefreshToken,
+ Expiry: tj.expiry(),
+ Raw: make(map[string]interface{}),
+ }
+ json.Unmarshal(body, &token.Raw) // no error checks for optional fields
+ }
+ // Don't overwrite `RefreshToken` with an empty value
+ // if this was a token refreshing request.
+ if token.RefreshToken == "" {
+ token.RefreshToken = v.Get("refresh_token")
+ }
+ return token, nil
+}
diff --git a/vendor/golang.org/x/oauth2/internal/token_test.go b/vendor/golang.org/x/oauth2/internal/token_test.go
new file mode 100644
index 0000000..df5eb26
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/token_test.go
@@ -0,0 +1,104 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "testing"
+
+ "golang.org/x/net/context"
+)
+
+func TestRegisterBrokenAuthHeaderProvider(t *testing.T) {
+ RegisterBrokenAuthHeaderProvider("https://aaa.com/")
+ tokenURL := "https://aaa.com/token"
+ if providerAuthHeaderWorks(tokenURL) {
+ t.Errorf("got %q as unbroken; want broken", tokenURL)
+ }
+}
+
+func TestRetrieveTokenBustedNoSecret(t *testing.T) {
+ const clientID = "client-id"
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if got, want := r.FormValue("client_id"), clientID; got != want {
+ t.Errorf("client_id = %q; want %q", got, want)
+ }
+ if got, want := r.FormValue("client_secret"), ""; got != want {
+ t.Errorf("client_secret = %q; want empty", got)
+ }
+ }))
+ defer ts.Close()
+
+ RegisterBrokenAuthHeaderProvider(ts.URL)
+ _, err := RetrieveToken(context.Background(), clientID, "", ts.URL, url.Values{})
+ if err != nil {
+ t.Errorf("RetrieveToken = %v; want no error", err)
+ }
+}
+
+func Test_providerAuthHeaderWorks(t *testing.T) {
+ for _, p := range brokenAuthHeaderProviders {
+ if providerAuthHeaderWorks(p) {
+ t.Errorf("got %q as unbroken; want broken", p)
+ }
+ p := fmt.Sprintf("%ssomesuffix", p)
+ if providerAuthHeaderWorks(p) {
+ t.Errorf("got %q as unbroken; want broken", p)
+ }
+ }
+ p := "https://api.not-in-the-list-example.com/"
+ if !providerAuthHeaderWorks(p) {
+ t.Errorf("got %q as unbroken; want broken", p)
+ }
+}
+
+func TestProviderAuthHeaderWorksDomain(t *testing.T) {
+ tests := []struct {
+ tokenURL string
+ wantWorks bool
+ }{
+ {"https://dev-12345.okta.com/token-url", false},
+ {"https://dev-12345.oktapreview.com/token-url", false},
+ {"https://dev-12345.okta.org/token-url", true},
+ {"https://foo.bar.force.com/token-url", false},
+ {"https://foo.force.com/token-url", false},
+ {"https://force.com/token-url", true},
+ }
+
+ for _, test := range tests {
+ got := providerAuthHeaderWorks(test.tokenURL)
+ if got != test.wantWorks {
+ t.Errorf("providerAuthHeaderWorks(%q) = %v; want %v", test.tokenURL, got, test.wantWorks)
+ }
+ }
+}
+
+func TestRetrieveTokenWithContexts(t *testing.T) {
+ const clientID = "client-id"
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
+ defer ts.Close()
+
+ _, err := RetrieveToken(context.Background(), clientID, "", ts.URL, url.Values{})
+ if err != nil {
+ t.Errorf("RetrieveToken (with background context) = %v; want no error", err)
+ }
+
+ ctx, cancelfunc := context.WithCancel(context.Background())
+
+ cancellingts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ cancelfunc()
+ }))
+ defer cancellingts.Close()
+
+ _, err = RetrieveToken(ctx, clientID, "", cancellingts.URL, url.Values{})
+ if err == nil {
+ t.Errorf("RetrieveToken (with cancelled context) = nil; want error")
+ }
+}
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..783bd98
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/transport.go
@@ -0,0 +1,68 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "net/http"
+
+ "golang.org/x/net/context"
+)
+
+// HTTPClient is the context key to use with golang.org/x/net/context's
+// WithValue function to associate an *http.Client value with a context.
+var HTTPClient ContextKey
+
+// ContextKey is just an empty struct. It exists so HTTPClient can be
+// an immutable public variable with a unique type. It's immutable
+// because nobody else can create a ContextKey, being unexported.
+type ContextKey struct{}
+
+// ContextClientFunc is a func which tries to return an *http.Client
+// given a Context value. If it returns an error, the search stops
+// with that error. If it returns (nil, nil), the search continues
+// down the list of registered funcs.
+type ContextClientFunc func(context.Context) (*http.Client, error)
+
+var contextClientFuncs []ContextClientFunc
+
+func RegisterContextClientFunc(fn ContextClientFunc) {
+ contextClientFuncs = append(contextClientFuncs, fn)
+}
+
+func ContextClient(ctx context.Context) (*http.Client, error) {
+ if ctx != nil {
+ if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok {
+ return hc, nil
+ }
+ }
+ for _, fn := range contextClientFuncs {
+ c, err := fn(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if c != nil {
+ return c, nil
+ }
+ }
+ return http.DefaultClient, nil
+}
+
+func ContextTransport(ctx context.Context) http.RoundTripper {
+ hc, err := ContextClient(ctx)
+ // This is a rare error case (somebody using nil on App Engine).
+ if err != nil {
+ return ErrorTransport{err}
+ }
+ return hc.Transport
+}
+
+// ErrorTransport returns the specified error on RoundTrip.
+// This RoundTripper should be used in rare error cases where
+// error handling can be postponed to response handling time.
+type ErrorTransport struct{ Err error }
+
+func (t ErrorTransport) RoundTrip(*http.Request) (*http.Response, error) {
+ return nil, t.Err
+}
diff --git a/vendor/golang.org/x/oauth2/internal/transport_test.go b/vendor/golang.org/x/oauth2/internal/transport_test.go
new file mode 100644
index 0000000..8772ec5
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/transport_test.go
@@ -0,0 +1,38 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "net/http"
+ "testing"
+
+ "golang.org/x/net/context"
+)
+
+func TestContextClient(t *testing.T) {
+ rc := &http.Client{}
+ RegisterContextClientFunc(func(context.Context) (*http.Client, error) {
+ return rc, nil
+ })
+
+ c := &http.Client{}
+ ctx := context.WithValue(context.Background(), HTTPClient, c)
+
+ hc, err := ContextClient(ctx)
+ if err != nil {
+ t.Fatalf("want valid client; got err = %v", err)
+ }
+ if hc != c {
+ t.Fatalf("want context client = %p; got = %p", c, hc)
+ }
+
+ hc, err = ContextClient(context.TODO())
+ if err != nil {
+ t.Fatalf("want valid client; got err = %v", err)
+ }
+ if hc != rc {
+ t.Fatalf("want registered client = %p; got = %p", c, hc)
+ }
+}
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 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package jws provides a partial implementation
+// of JSON Web Signature encoding and decoding.
+// It exists to support the golang.org/x/oauth2 package.
+//
+// See RFC 7515.
+//
+// Deprecated: this package is not intended for public use and might be
+// removed in the future. It exists for internal use only.
+// Please switch to another JWS package or copy this package into your own
+// source tree.
+package jws // import "golang.org/x/oauth2/jws"
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+)
+
+// ClaimSet contains information about the JWT signature including the
+// permissions being requested (scopes), the target of the token, the issuer,
+// the time the token was issued, and the lifetime of the token.
+type ClaimSet struct {
+ Iss string `json:"iss"` // email address of the client_id of the application making the access token request
+ Scope string `json:"scope,omitempty"` // space-delimited list of the permissions the application requests
+ Aud string `json:"aud"` // descriptor of the intended target of the assertion (Optional).
+ Exp int64 `json:"exp"` // the expiration time of the assertion (seconds since Unix epoch)
+ Iat int64 `json:"iat"` // the time the assertion was issued (seconds since Unix epoch)
+ Typ string `json:"typ,omitempty"` // token type (Optional).
+
+ // Email for which the application is requesting delegated access (Optional).
+ Sub string `json:"sub,omitempty"`
+
+ // The old name of Sub. Client keeps setting Prn to be
+ // complaint with legacy OAuth 2.0 providers. (Optional)
+ Prn string `json:"prn,omitempty"`
+
+ // See http://tools.ietf.org/html/draft-jones-json-web-token-10#section-4.3
+ // This array is marshalled using custom code (see (c *ClaimSet) encode()).
+ PrivateClaims map[string]interface{} `json:"-"`
+}
+
+func (c *ClaimSet) encode() (string, error) {
+ // Reverting time back for machines whose time is not perfectly in sync.
+ // If client machine's time is in the future according
+ // to Google servers, an access token will not be issued.
+ now := time.Now().Add(-10 * time.Second)
+ if c.Iat == 0 {
+ c.Iat = now.Unix()
+ }
+ if c.Exp == 0 {
+ c.Exp = now.Add(time.Hour).Unix()
+ }
+ if c.Exp < c.Iat {
+ return "", fmt.Errorf("jws: invalid Exp = %v; must be later than Iat = %v", c.Exp, c.Iat)
+ }
+
+ b, err := json.Marshal(c)
+ if err != nil {
+ return "", err
+ }
+
+ if len(c.PrivateClaims) == 0 {
+ return base64.RawURLEncoding.EncodeToString(b), nil
+ }
+
+ // Marshal private claim set and then append it to b.
+ prv, err := json.Marshal(c.PrivateClaims)
+ if err != nil {
+ return "", fmt.Errorf("jws: invalid map of private claims %v", c.PrivateClaims)
+ }
+
+ // Concatenate public and private claim JSON objects.
+ if !bytes.HasSuffix(b, []byte{'}'}) {
+ return "", fmt.Errorf("jws: invalid JSON %s", b)
+ }
+ if !bytes.HasPrefix(prv, []byte{'{'}) {
+ return "", fmt.Errorf("jws: invalid JSON %s", prv)
+ }
+ b[len(b)-1] = ',' // Replace closing curly brace with a comma.
+ b = append(b, prv[1:]...) // Append private claims.
+ return base64.RawURLEncoding.EncodeToString(b), nil
+}
+
+// Header represents the header for the signed JWS payloads.
+type Header struct {
+ // The algorithm used for signature.
+ Algorithm string `json:"alg"`
+
+ // Represents the token type.
+ Typ string `json:"typ"`
+
+ // The optional hint of which key is being used.
+ KeyID string `json:"kid,omitempty"`
+}
+
+func (h *Header) encode() (string, error) {
+ b, err := json.Marshal(h)
+ if err != nil {
+ return "", err
+ }
+ return base64.RawURLEncoding.EncodeToString(b), nil
+}
+
+// Decode decodes a claim set from a JWS payload.
+func Decode(payload string) (*ClaimSet, error) {
+ // decode returned id token to get expiry
+ s := strings.Split(payload, ".")
+ if len(s) < 2 {
+ // TODO(jbd): Provide more context about the error.
+ return nil, errors.New("jws: invalid token received")
+ }
+ decoded, err := base64.RawURLEncoding.DecodeString(s[1])
+ if err != nil {
+ return nil, err
+ }
+ c := &ClaimSet{}
+ err = json.NewDecoder(bytes.NewBuffer(decoded)).Decode(c)
+ return c, err
+}
+
+// Signer returns a signature for the given data.
+type Signer func(data []byte) (sig []byte, err error)
+
+// EncodeWithSigner encodes a header and claim set with the provided signer.
+func EncodeWithSigner(header *Header, c *ClaimSet, sg Signer) (string, error) {
+ head, err := header.encode()
+ if err != nil {
+ return "", err
+ }
+ cs, err := c.encode()
+ if err != nil {
+ return "", err
+ }
+ ss := fmt.Sprintf("%s.%s", head, cs)
+ sig, err := sg([]byte(ss))
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%s.%s", ss, base64.RawURLEncoding.EncodeToString(sig)), nil
+}
+
+// Encode encodes a signed JWS with provided header and claim set.
+// This invokes EncodeWithSigner using crypto/rsa.SignPKCS1v15 with the given RSA private key.
+func Encode(header *Header, c *ClaimSet, key *rsa.PrivateKey) (string, error) {
+ sg := func(data []byte) (sig []byte, err error) {
+ h := sha256.New()
+ h.Write(data)
+ return rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, h.Sum(nil))
+ }
+ return EncodeWithSigner(header, c, sg)
+}
+
+// Verify tests whether the provided JWT token's signature was produced by the private key
+// associated with the supplied public key.
+func Verify(token string, key *rsa.PublicKey) error {
+ parts := strings.Split(token, ".")
+ if len(parts) != 3 {
+ return errors.New("jws: invalid token received, token must have 3 parts")
+ }
+
+ signedContent := parts[0] + "." + parts[1]
+ signatureString, err := base64.RawURLEncoding.DecodeString(parts[2])
+ if err != nil {
+ return err
+ }
+
+ h := sha256.New()
+ h.Write([]byte(signedContent))
+ return rsa.VerifyPKCS1v15(key, crypto.SHA256, h.Sum(nil), []byte(signatureString))
+}
diff --git a/vendor/golang.org/x/oauth2/jws/jws_test.go b/vendor/golang.org/x/oauth2/jws/jws_test.go
new file mode 100644
index 0000000..39a136a
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/jws/jws_test.go
@@ -0,0 +1,46 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jws
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "testing"
+)
+
+func TestSignAndVerify(t *testing.T) {
+ header := &Header{
+ Algorithm: "RS256",
+ Typ: "JWT",
+ }
+ payload := &ClaimSet{
+ Iss: "http://google.com/",
+ Aud: "",
+ Exp: 3610,
+ Iat: 10,
+ }
+
+ privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ token, err := Encode(header, payload, privateKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = Verify(token, &privateKey.PublicKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestVerifyFailsOnMalformedClaim(t *testing.T) {
+ err := Verify("abc.def", nil)
+ if err == nil {
+ t.Error("got no errors; want improperly formed JWT not to be verified")
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/jwt/example_test.go b/vendor/golang.org/x/oauth2/jwt/example_test.go
new file mode 100644
index 0000000..58503d8
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/jwt/example_test.go
@@ -0,0 +1,33 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jwt_test
+
+import (
+ "context"
+
+ "golang.org/x/oauth2/jwt"
+)
+
+func ExampleJWTConfig() {
+ ctx := context.Background()
+ conf := &jwt.Config{
+ Email: "xxx@developer.com",
+ // The contents of your RSA private key or your PEM file
+ // that contains a private key.
+ // If you have a p12 file instead, you
+ // can use `openssl` to export the private key into a pem file.
+ //
+ // $ openssl pkcs12 -in key.p12 -out key.pem -nodes
+ //
+ // It only supports PEM containers with no passphrase.
+ PrivateKey: []byte("-----BEGIN RSA PRIVATE KEY-----..."),
+ Subject: "user@example.com",
+ TokenURL: "https://provider.com/o/oauth2/token",
+ }
+ // Initiate an http.Client, the following GET request will be
+ // authorized and authenticated on the behalf of user@example.com.
+ client := conf.Client(ctx)
+ client.Get("...")
+}
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..e016db4
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/jwt/jwt.go
@@ -0,0 +1,159 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package jwt implements the OAuth 2.0 JSON Web Token flow, commonly
+// known as "two-legged OAuth 2.0".
+//
+// See: https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12
+package jwt
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+ "golang.org/x/oauth2/jws"
+)
+
+var (
+ defaultGrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"
+ defaultHeader = &jws.Header{Algorithm: "RS256", Typ: "JWT"}
+)
+
+// Config is the configuration for using JWT to fetch tokens,
+// commonly known as "two-legged OAuth 2.0".
+type Config struct {
+ // Email is the OAuth client identifier used when communicating with
+ // the configured OAuth provider.
+ Email string
+
+ // PrivateKey contains the contents of an RSA private key or the
+ // contents of a PEM file that contains a private key. The provided
+ // private key is used to sign JWT payloads.
+ // PEM containers with a passphrase are not supported.
+ // Use the following command to convert a PKCS 12 file into a PEM.
+ //
+ // $ openssl pkcs12 -in key.p12 -out key.pem -nodes
+ //
+ PrivateKey []byte
+
+ // PrivateKeyID contains an optional hint indicating which key is being
+ // used.
+ PrivateKeyID string
+
+ // Subject is the optional user to impersonate.
+ Subject string
+
+ // Scopes optionally specifies a list of requested permission scopes.
+ Scopes []string
+
+ // TokenURL is the endpoint required to complete the 2-legged JWT flow.
+ TokenURL string
+
+ // Expires optionally specifies how long the token is valid for.
+ Expires time.Duration
+}
+
+// TokenSource returns a JWT TokenSource using the configuration
+// in c and the HTTP client from the provided context.
+func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
+ return oauth2.ReuseTokenSource(nil, jwtSource{ctx, c})
+}
+
+// Client returns an HTTP client wrapping the context's
+// HTTP transport and adding Authorization headers with tokens
+// obtained from c.
+//
+// The returned client and its Transport should not be modified.
+func (c *Config) Client(ctx context.Context) *http.Client {
+ return oauth2.NewClient(ctx, c.TokenSource(ctx))
+}
+
+// jwtSource is a source that always does a signed JWT request for a token.
+// It should typically be wrapped with a reuseTokenSource.
+type jwtSource struct {
+ ctx context.Context
+ conf *Config
+}
+
+func (js jwtSource) Token() (*oauth2.Token, error) {
+ pk, err := internal.ParseKey(js.conf.PrivateKey)
+ if err != nil {
+ return nil, err
+ }
+ hc := oauth2.NewClient(js.ctx, nil)
+ claimSet := &jws.ClaimSet{
+ Iss: js.conf.Email,
+ Scope: strings.Join(js.conf.Scopes, " "),
+ Aud: js.conf.TokenURL,
+ }
+ if subject := js.conf.Subject; subject != "" {
+ claimSet.Sub = subject
+ // prn is the old name of sub. Keep setting it
+ // to be compatible with legacy OAuth 2.0 providers.
+ claimSet.Prn = subject
+ }
+ if t := js.conf.Expires; t > 0 {
+ claimSet.Exp = time.Now().Add(t).Unix()
+ }
+ h := *defaultHeader
+ h.KeyID = js.conf.PrivateKeyID
+ payload, err := jws.Encode(&h, claimSet, pk)
+ if err != nil {
+ return nil, err
+ }
+ v := url.Values{}
+ v.Set("grant_type", defaultGrantType)
+ v.Set("assertion", payload)
+ resp, err := hc.PostForm(js.conf.TokenURL, v)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ if c := resp.StatusCode; c < 200 || c > 299 {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", resp.Status, body)
+ }
+ // tokenRes is the JSON response body.
+ var tokenRes struct {
+ AccessToken string `json:"access_token"`
+ TokenType string `json:"token_type"`
+ IDToken string `json:"id_token"`
+ ExpiresIn int64 `json:"expires_in"` // relative seconds from now
+ }
+ if err := json.Unmarshal(body, &tokenRes); err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ token := &oauth2.Token{
+ AccessToken: tokenRes.AccessToken,
+ TokenType: tokenRes.TokenType,
+ }
+ raw := make(map[string]interface{})
+ json.Unmarshal(body, &raw) // no error checks for optional fields
+ token = token.WithExtra(raw)
+
+ if secs := tokenRes.ExpiresIn; secs > 0 {
+ token.Expiry = time.Now().Add(time.Duration(secs) * time.Second)
+ }
+ if v := tokenRes.IDToken; v != "" {
+ // decode returned id token to get expiry
+ claimSet, err := jws.Decode(v)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: error decoding JWT token: %v", err)
+ }
+ token.Expiry = time.Unix(claimSet.Exp, 0)
+ }
+ return token, nil
+}
diff --git a/vendor/golang.org/x/oauth2/jwt/jwt_test.go b/vendor/golang.org/x/oauth2/jwt/jwt_test.go
new file mode 100644
index 0000000..9f82c71
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/jwt/jwt_test.go
@@ -0,0 +1,190 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jwt
+
+import (
+ "context"
+ "encoding/base64"
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ "golang.org/x/oauth2/jws"
+)
+
+var dummyPrivateKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAx4fm7dngEmOULNmAs1IGZ9Apfzh+BkaQ1dzkmbUgpcoghucE
+DZRnAGd2aPyB6skGMXUytWQvNYav0WTR00wFtX1ohWTfv68HGXJ8QXCpyoSKSSFY
+fuP9X36wBSkSX9J5DVgiuzD5VBdzUISSmapjKm+DcbRALjz6OUIPEWi1Tjl6p5RK
+1w41qdbmt7E5/kGhKLDuT7+M83g4VWhgIvaAXtnhklDAggilPPa8ZJ1IFe31lNlr
+k4DRk38nc6sEutdf3RL7QoH7FBusI7uXV03DC6dwN1kP4GE7bjJhcRb/7jYt7CQ9
+/E9Exz3c0yAp0yrTg0Fwh+qxfH9dKwN52S7SBwIDAQABAoIBAQCaCs26K07WY5Jt
+3a2Cw3y2gPrIgTCqX6hJs7O5ByEhXZ8nBwsWANBUe4vrGaajQHdLj5OKfsIDrOvn
+2NI1MqflqeAbu/kR32q3tq8/Rl+PPiwUsW3E6Pcf1orGMSNCXxeducF2iySySzh3
+nSIhCG5uwJDWI7a4+9KiieFgK1pt/Iv30q1SQS8IEntTfXYwANQrfKUVMmVF9aIK
+6/WZE2yd5+q3wVVIJ6jsmTzoDCX6QQkkJICIYwCkglmVy5AeTckOVwcXL0jqw5Kf
+5/soZJQwLEyBoQq7Kbpa26QHq+CJONetPP8Ssy8MJJXBT+u/bSseMb3Zsr5cr43e
+DJOhwsThAoGBAPY6rPKl2NT/K7XfRCGm1sbWjUQyDShscwuWJ5+kD0yudnT/ZEJ1
+M3+KS/iOOAoHDdEDi9crRvMl0UfNa8MAcDKHflzxg2jg/QI+fTBjPP5GOX0lkZ9g
+z6VePoVoQw2gpPFVNPPTxKfk27tEzbaffvOLGBEih0Kb7HTINkW8rIlzAoGBAM9y
+1yr+jvfS1cGFtNU+Gotoihw2eMKtIqR03Yn3n0PK1nVCDKqwdUqCypz4+ml6cxRK
+J8+Pfdh7D+ZJd4LEG6Y4QRDLuv5OA700tUoSHxMSNn3q9As4+T3MUyYxWKvTeu3U
+f2NWP9ePU0lV8ttk7YlpVRaPQmc1qwooBA/z/8AdAoGAW9x0HWqmRICWTBnpjyxx
+QGlW9rQ9mHEtUotIaRSJ6K/F3cxSGUEkX1a3FRnp6kPLcckC6NlqdNgNBd6rb2rA
+cPl/uSkZP42Als+9YMoFPU/xrrDPbUhu72EDrj3Bllnyb168jKLa4VBOccUvggxr
+Dm08I1hgYgdN5huzs7y6GeUCgYEAj+AZJSOJ6o1aXS6rfV3mMRve9bQ9yt8jcKXw
+5HhOCEmMtaSKfnOF1Ziih34Sxsb7O2428DiX0mV/YHtBnPsAJidL0SdLWIapBzeg
+KHArByIRkwE6IvJvwpGMdaex1PIGhx5i/3VZL9qiq/ElT05PhIb+UXgoWMabCp84
+OgxDK20CgYAeaFo8BdQ7FmVX2+EEejF+8xSge6WVLtkaon8bqcn6P0O8lLypoOhd
+mJAYH8WU+UAy9pecUnDZj14LAGNVmYcse8HFX71MoshnvCTFEPVo4rZxIAGwMpeJ
+5jgQ3slYLpqrGlcbLgUXBUgzEO684Wk/UV9DFPlHALVqCfXQ9dpJPg==
+-----END RSA PRIVATE KEY-----`)
+
+func TestJWTFetch_JSONResponse(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{
+ "access_token": "90d64460d14870c08c81352a05dedd3465940a7c",
+ "scope": "user",
+ "token_type": "bearer",
+ "expires_in": 3600
+ }`))
+ }))
+ defer ts.Close()
+
+ conf := &Config{
+ Email: "aaa@xxx.com",
+ PrivateKey: dummyPrivateKey,
+ TokenURL: ts.URL,
+ }
+ tok, err := conf.TokenSource(context.Background()).Token()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !tok.Valid() {
+ t.Errorf("got invalid token: %v", tok)
+ }
+ if got, want := tok.AccessToken, "90d64460d14870c08c81352a05dedd3465940a7c"; got != want {
+ t.Errorf("access token = %q; want %q", got, want)
+ }
+ if got, want := tok.TokenType, "bearer"; got != want {
+ t.Errorf("token type = %q; want %q", got, want)
+ }
+ if got := tok.Expiry.IsZero(); got {
+ t.Errorf("token expiry = %v, want none", got)
+ }
+ scope := tok.Extra("scope")
+ if got, want := scope, "user"; got != want {
+ t.Errorf("scope = %q; want %q", got, want)
+ }
+}
+
+func TestJWTFetch_BadResponse(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{"scope": "user", "token_type": "bearer"}`))
+ }))
+ defer ts.Close()
+
+ conf := &Config{
+ Email: "aaa@xxx.com",
+ PrivateKey: dummyPrivateKey,
+ TokenURL: ts.URL,
+ }
+ tok, err := conf.TokenSource(context.Background()).Token()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if tok == nil {
+ t.Fatalf("got nil token; want token")
+ }
+ if tok.Valid() {
+ t.Errorf("got invalid token: %v", tok)
+ }
+ if got, want := tok.AccessToken, ""; got != want {
+ t.Errorf("access token = %q; want %q", got, want)
+ }
+ if got, want := tok.TokenType, "bearer"; got != want {
+ t.Errorf("token type = %q; want %q", got, want)
+ }
+ scope := tok.Extra("scope")
+ if got, want := scope, "user"; got != want {
+ t.Errorf("token scope = %q; want %q", got, want)
+ }
+}
+
+func TestJWTFetch_BadResponseType(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{"access_token":123, "scope": "user", "token_type": "bearer"}`))
+ }))
+ defer ts.Close()
+ conf := &Config{
+ Email: "aaa@xxx.com",
+ PrivateKey: dummyPrivateKey,
+ TokenURL: ts.URL,
+ }
+ tok, err := conf.TokenSource(context.Background()).Token()
+ if err == nil {
+ t.Error("got a token; expected error")
+ if got, want := tok.AccessToken, ""; got != want {
+ t.Errorf("access token = %q; want %q", got, want)
+ }
+ }
+}
+
+func TestJWTFetch_Assertion(t *testing.T) {
+ var assertion string
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ r.ParseForm()
+ assertion = r.Form.Get("assertion")
+
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{
+ "access_token": "90d64460d14870c08c81352a05dedd3465940a7c",
+ "scope": "user",
+ "token_type": "bearer",
+ "expires_in": 3600
+ }`))
+ }))
+ defer ts.Close()
+
+ conf := &Config{
+ Email: "aaa@xxx.com",
+ PrivateKey: dummyPrivateKey,
+ PrivateKeyID: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ TokenURL: ts.URL,
+ }
+
+ _, err := conf.TokenSource(context.Background()).Token()
+ if err != nil {
+ t.Fatalf("Failed to fetch token: %v", err)
+ }
+
+ parts := strings.Split(assertion, ".")
+ if len(parts) != 3 {
+ t.Fatalf("assertion = %q; want 3 parts", assertion)
+ }
+ gotjson, err := base64.RawURLEncoding.DecodeString(parts[0])
+ if err != nil {
+ t.Fatalf("invalid token header; err = %v", err)
+ }
+
+ got := jws.Header{}
+ if err := json.Unmarshal(gotjson, &got); err != nil {
+ t.Errorf("failed to unmarshal json token header = %q; err = %v", gotjson, err)
+ }
+
+ want := jws.Header{
+ Algorithm: "RS256",
+ Typ: "JWT",
+ KeyID: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ }
+ if got != want {
+ t.Errorf("access token header = %q; want %q", got, want)
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/linkedin/linkedin.go b/vendor/golang.org/x/oauth2/linkedin/linkedin.go
new file mode 100644
index 0000000..b619f93
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/linkedin/linkedin.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package linkedin provides constants for using OAuth2 to access LinkedIn.
+package linkedin // import "golang.org/x/oauth2/linkedin"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is LinkedIn's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.linkedin.com/uas/oauth2/authorization",
+ TokenURL: "https://www.linkedin.com/uas/oauth2/accessToken",
+}
diff --git a/vendor/golang.org/x/oauth2/mediamath/mediamath.go b/vendor/golang.org/x/oauth2/mediamath/mediamath.go
new file mode 100644
index 0000000..3ebce5d
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/mediamath/mediamath.go
@@ -0,0 +1,22 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package mediamath provides constants for using OAuth2 to access MediaMath.
+package mediamath // import "golang.org/x/oauth2/mediamath"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is MediaMath's OAuth 2.0 endpoint for production.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://api.mediamath.com/oauth2/v1.0/authorize",
+ TokenURL: "https://api.mediamath.com/oauth2/v1.0/token",
+}
+
+// SandboxEndpoint is MediaMath's OAuth 2.0 endpoint for sandbox.
+var SandboxEndpoint = oauth2.Endpoint{
+ AuthURL: "https://t1sandbox.mediamath.com/oauth2/v1.0/authorize",
+ TokenURL: "https://t1sandbox.mediamath.com/oauth2/v1.0/token",
+}
diff --git a/vendor/golang.org/x/oauth2/microsoft/microsoft.go b/vendor/golang.org/x/oauth2/microsoft/microsoft.go
new file mode 100644
index 0000000..f21b398
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/microsoft/microsoft.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package microsoft provides constants for using OAuth2 to access Windows Live ID.
+package microsoft // import "golang.org/x/oauth2/microsoft"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// LiveConnectEndpoint is Windows's Live ID OAuth 2.0 endpoint.
+var LiveConnectEndpoint = oauth2.Endpoint{
+ AuthURL: "https://login.live.com/oauth20_authorize.srf",
+ TokenURL: "https://login.live.com/oauth20_token.srf",
+}
diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go
new file mode 100644
index 0000000..4bafe87
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/oauth2.go
@@ -0,0 +1,344 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package oauth2 provides support for making
+// OAuth2 authorized and authenticated HTTP requests.
+// It can additionally grant authorization with Bearer JWT.
+package oauth2 // import "golang.org/x/oauth2"
+
+import (
+ "bytes"
+ "errors"
+ "net/http"
+ "net/url"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2/internal"
+)
+
+// NoContext is the default context you should supply if not using
+// your own context.Context (see https://golang.org/x/net/context).
+//
+// Deprecated: Use context.Background() or context.TODO() instead.
+var NoContext = context.TODO()
+
+// RegisterBrokenAuthHeaderProvider registers an OAuth2 server
+// identified by the tokenURL prefix as an OAuth2 implementation
+// which doesn't support the HTTP Basic authentication
+// scheme to authenticate with the authorization server.
+// Once a server is registered, credentials (client_id and client_secret)
+// will be passed as query parameters rather than being present
+// in the Authorization header.
+// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
+func RegisterBrokenAuthHeaderProvider(tokenURL string) {
+ internal.RegisterBrokenAuthHeaderProvider(tokenURL)
+}
+
+// Config describes a typical 3-legged OAuth2 flow, with both the
+// client application information and the server's endpoint URLs.
+// For the client credentials 2-legged OAuth2 flow, see the clientcredentials
+// package (https://golang.org/x/oauth2/clientcredentials).
+type Config struct {
+ // ClientID is the application's ID.
+ ClientID string
+
+ // ClientSecret is the application's secret.
+ ClientSecret string
+
+ // Endpoint contains the resource server's token endpoint
+ // URLs. These are constants specific to each server and are
+ // often available via site-specific packages, such as
+ // google.Endpoint or github.Endpoint.
+ Endpoint Endpoint
+
+ // RedirectURL is the URL to redirect users going through
+ // the OAuth flow, after the resource owner's URLs.
+ RedirectURL string
+
+ // Scope specifies optional requested permissions.
+ Scopes []string
+}
+
+// A TokenSource is anything that can return a token.
+type TokenSource interface {
+ // Token returns a token or an error.
+ // Token must be safe for concurrent use by multiple goroutines.
+ // The returned Token must not be modified.
+ Token() (*Token, error)
+}
+
+// Endpoint contains the OAuth 2.0 provider's authorization and token
+// endpoint URLs.
+type Endpoint struct {
+ AuthURL string
+ TokenURL string
+}
+
+var (
+ // AccessTypeOnline and AccessTypeOffline are options passed
+ // to the Options.AuthCodeURL method. They modify the
+ // "access_type" field that gets sent in the URL returned by
+ // AuthCodeURL.
+ //
+ // Online is the default if neither is specified. If your
+ // application needs to refresh access tokens when the user
+ // is not present at the browser, then use offline. This will
+ // result in your application obtaining a refresh token the
+ // first time your application exchanges an authorization
+ // code for a user.
+ AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online")
+ AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline")
+
+ // ApprovalForce forces the users to view the consent dialog
+ // and confirm the permissions request at the URL returned
+ // from AuthCodeURL, even if they've already done so.
+ ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force")
+)
+
+// An AuthCodeOption is passed to Config.AuthCodeURL.
+type AuthCodeOption interface {
+ setValue(url.Values)
+}
+
+type setParam struct{ k, v string }
+
+func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) }
+
+// SetAuthURLParam builds an AuthCodeOption which passes key/value parameters
+// to a provider's authorization endpoint.
+func SetAuthURLParam(key, value string) AuthCodeOption {
+ return setParam{key, value}
+}
+
+// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
+// that asks for permissions for the required scopes explicitly.
+//
+// State is a token to protect the user from CSRF attacks. You must
+// always provide a non-zero string and validate that it matches the
+// the state query parameter on your redirect callback.
+// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
+//
+// Opts may include AccessTypeOnline or AccessTypeOffline, as well
+// as ApprovalForce.
+func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
+ var buf bytes.Buffer
+ buf.WriteString(c.Endpoint.AuthURL)
+ v := url.Values{
+ "response_type": {"code"},
+ "client_id": {c.ClientID},
+ "redirect_uri": internal.CondVal(c.RedirectURL),
+ "scope": internal.CondVal(strings.Join(c.Scopes, " ")),
+ "state": internal.CondVal(state),
+ }
+ for _, opt := range opts {
+ opt.setValue(v)
+ }
+ if strings.Contains(c.Endpoint.AuthURL, "?") {
+ buf.WriteByte('&')
+ } else {
+ buf.WriteByte('?')
+ }
+ buf.WriteString(v.Encode())
+ return buf.String()
+}
+
+// PasswordCredentialsToken converts a resource owner username and password
+// pair into a token.
+//
+// Per the RFC, this grant type should only be used "when there is a high
+// degree of trust between the resource owner and the client (e.g., the client
+// is part of the device operating system or a highly privileged application),
+// and when other authorization grant types are not available."
+// See https://tools.ietf.org/html/rfc6749#section-4.3 for more info.
+//
+// The HTTP client to use is derived from the context.
+// If nil, http.DefaultClient is used.
+func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) {
+ return retrieveToken(ctx, c, url.Values{
+ "grant_type": {"password"},
+ "username": {username},
+ "password": {password},
+ "scope": internal.CondVal(strings.Join(c.Scopes, " ")),
+ })
+}
+
+// Exchange converts an authorization code into a token.
+//
+// It is used after a resource provider redirects the user back
+// to the Redirect URI (the URL obtained from AuthCodeURL).
+//
+// The HTTP client to use is derived from the context.
+// If a client is not provided via the context, http.DefaultClient is used.
+//
+// The code will be in the *http.Request.FormValue("code"). Before
+// calling Exchange, be sure to validate FormValue("state").
+func (c *Config) Exchange(ctx context.Context, code string) (*Token, error) {
+ return retrieveToken(ctx, c, url.Values{
+ "grant_type": {"authorization_code"},
+ "code": {code},
+ "redirect_uri": internal.CondVal(c.RedirectURL),
+ })
+}
+
+// Client returns an HTTP client using the provided token.
+// The token will auto-refresh as necessary. The underlying
+// HTTP transport will be obtained using the provided context.
+// The returned client and its Transport should not be modified.
+func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
+ return NewClient(ctx, c.TokenSource(ctx, t))
+}
+
+// TokenSource returns a TokenSource that returns t until t expires,
+// automatically refreshing it as necessary using the provided context.
+//
+// Most users will use Config.Client instead.
+func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
+ tkr := &tokenRefresher{
+ ctx: ctx,
+ conf: c,
+ }
+ if t != nil {
+ tkr.refreshToken = t.RefreshToken
+ }
+ return &reuseTokenSource{
+ t: t,
+ new: tkr,
+ }
+}
+
+// tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token"
+// HTTP requests to renew a token using a RefreshToken.
+type tokenRefresher struct {
+ ctx context.Context // used to get HTTP requests
+ conf *Config
+ refreshToken string
+}
+
+// WARNING: Token is not safe for concurrent access, as it
+// updates the tokenRefresher's refreshToken field.
+// Within this package, it is used by reuseTokenSource which
+// synchronizes calls to this method with its own mutex.
+func (tf *tokenRefresher) Token() (*Token, error) {
+ if tf.refreshToken == "" {
+ return nil, errors.New("oauth2: token expired and refresh token is not set")
+ }
+
+ tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{
+ "grant_type": {"refresh_token"},
+ "refresh_token": {tf.refreshToken},
+ })
+
+ if err != nil {
+ return nil, err
+ }
+ if tf.refreshToken != tk.RefreshToken {
+ tf.refreshToken = tk.RefreshToken
+ }
+ return tk, err
+}
+
+// reuseTokenSource is a TokenSource that holds a single token in memory
+// and validates its expiry before each call to retrieve it with
+// Token. If it's expired, it will be auto-refreshed using the
+// new TokenSource.
+type reuseTokenSource struct {
+ new TokenSource // called when t is expired.
+
+ mu sync.Mutex // guards t
+ t *Token
+}
+
+// Token returns the current token if it's still valid, else will
+// refresh the current token (using r.Context for HTTP client
+// information) and return the new one.
+func (s *reuseTokenSource) Token() (*Token, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.t.Valid() {
+ return s.t, nil
+ }
+ t, err := s.new.Token()
+ if err != nil {
+ return nil, err
+ }
+ s.t = t
+ return t, nil
+}
+
+// StaticTokenSource returns a TokenSource that always returns the same token.
+// Because the provided token t is never refreshed, StaticTokenSource is only
+// useful for tokens that never expire.
+func StaticTokenSource(t *Token) TokenSource {
+ return staticTokenSource{t}
+}
+
+// staticTokenSource is a TokenSource that always returns the same Token.
+type staticTokenSource struct {
+ t *Token
+}
+
+func (s staticTokenSource) Token() (*Token, error) {
+ return s.t, nil
+}
+
+// HTTPClient is the context key to use with golang.org/x/net/context's
+// WithValue function to associate an *http.Client value with a context.
+var HTTPClient internal.ContextKey
+
+// NewClient creates an *http.Client from a Context and TokenSource.
+// The returned client is not valid beyond the lifetime of the context.
+//
+// Note that if a custom *http.Client is provided via the Context it
+// is used only for token acquisition and is not used to configure the
+// *http.Client returned from NewClient.
+//
+// As a special case, if src is nil, a non-OAuth2 client is returned
+// using the provided context. This exists to support related OAuth2
+// packages.
+func NewClient(ctx context.Context, src TokenSource) *http.Client {
+ if src == nil {
+ c, err := internal.ContextClient(ctx)
+ if err != nil {
+ return &http.Client{Transport: internal.ErrorTransport{Err: err}}
+ }
+ return c
+ }
+ return &http.Client{
+ Transport: &Transport{
+ Base: internal.ContextTransport(ctx),
+ Source: ReuseTokenSource(nil, src),
+ },
+ }
+}
+
+// ReuseTokenSource returns a TokenSource which repeatedly returns the
+// same token as long as it's valid, starting with t.
+// When its cached token is invalid, a new token is obtained from src.
+//
+// ReuseTokenSource is typically used to reuse tokens from a cache
+// (such as a file on disk) between runs of a program, rather than
+// obtaining new tokens unnecessarily.
+//
+// The initial token t may be nil, in which case the TokenSource is
+// wrapped in a caching version if it isn't one already. This also
+// means it's always safe to wrap ReuseTokenSource around any other
+// TokenSource without adverse effects.
+func ReuseTokenSource(t *Token, src TokenSource) TokenSource {
+ // Don't wrap a reuseTokenSource in itself. That would work,
+ // but cause an unnecessary number of mutex operations.
+ // Just build the equivalent one.
+ if rt, ok := src.(*reuseTokenSource); ok {
+ if t == nil {
+ // Just use it directly.
+ return rt
+ }
+ src = rt.new
+ }
+ return &reuseTokenSource{
+ t: t,
+ new: src,
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/oauth2_test.go b/vendor/golang.org/x/oauth2/oauth2_test.go
new file mode 100644
index 0000000..09293ed
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/oauth2_test.go
@@ -0,0 +1,490 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2
+
+import (
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "testing"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+type mockTransport struct {
+ rt func(req *http.Request) (resp *http.Response, err error)
+}
+
+func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
+ return t.rt(req)
+}
+
+func newConf(url string) *Config {
+ return &Config{
+ ClientID: "CLIENT_ID",
+ ClientSecret: "CLIENT_SECRET",
+ RedirectURL: "REDIRECT_URL",
+ Scopes: []string{"scope1", "scope2"},
+ Endpoint: Endpoint{
+ AuthURL: url + "/auth",
+ TokenURL: url + "/token",
+ },
+ }
+}
+
+func TestAuthCodeURL(t *testing.T) {
+ conf := newConf("server")
+ url := conf.AuthCodeURL("foo", AccessTypeOffline, ApprovalForce)
+ const want = "server/auth?access_type=offline&approval_prompt=force&client_id=CLIENT_ID&redirect_uri=REDIRECT_URL&response_type=code&scope=scope1+scope2&state=foo"
+ if got := url; got != want {
+ t.Errorf("got auth code URL = %q; want %q", got, want)
+ }
+}
+
+func TestAuthCodeURL_CustomParam(t *testing.T) {
+ conf := newConf("server")
+ param := SetAuthURLParam("foo", "bar")
+ url := conf.AuthCodeURL("baz", param)
+ const want = "server/auth?client_id=CLIENT_ID&foo=bar&redirect_uri=REDIRECT_URL&response_type=code&scope=scope1+scope2&state=baz"
+ if got := url; got != want {
+ t.Errorf("got auth code = %q; want %q", got, want)
+ }
+}
+
+func TestAuthCodeURL_Optional(t *testing.T) {
+ conf := &Config{
+ ClientID: "CLIENT_ID",
+ Endpoint: Endpoint{
+ AuthURL: "/auth-url",
+ TokenURL: "/token-url",
+ },
+ }
+ url := conf.AuthCodeURL("")
+ const want = "/auth-url?client_id=CLIENT_ID&response_type=code"
+ if got := url; got != want {
+ t.Fatalf("got auth code = %q; want %q", got, want)
+ }
+}
+
+func TestURLUnsafeClientConfig(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if got, want := r.Header.Get("Authorization"), "Basic Q0xJRU5UX0lEJTNGJTNGOkNMSUVOVF9TRUNSRVQlM0YlM0Y="; got != want {
+ t.Errorf("Authorization header = %q; want %q", got, want)
+ }
+
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer"))
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ conf.ClientID = "CLIENT_ID??"
+ conf.ClientSecret = "CLIENT_SECRET??"
+ _, err := conf.Exchange(context.Background(), "exchange-code")
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestExchangeRequest(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.String() != "/token" {
+ t.Errorf("Unexpected exchange request URL, %v is found.", r.URL)
+ }
+ headerAuth := r.Header.Get("Authorization")
+ if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" {
+ t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
+ }
+ headerContentType := r.Header.Get("Content-Type")
+ if headerContentType != "application/x-www-form-urlencoded" {
+ t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
+ }
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ t.Errorf("Failed reading request body: %s.", err)
+ }
+ if string(body) != "code=exchange-code&grant_type=authorization_code&redirect_uri=REDIRECT_URL" {
+ t.Errorf("Unexpected exchange payload, %v is found.", string(body))
+ }
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer"))
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ tok, err := conf.Exchange(context.Background(), "exchange-code")
+ if err != nil {
+ t.Error(err)
+ }
+ if !tok.Valid() {
+ t.Fatalf("Token invalid. Got: %#v", tok)
+ }
+ if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" {
+ t.Errorf("Unexpected access token, %#v.", tok.AccessToken)
+ }
+ if tok.TokenType != "bearer" {
+ t.Errorf("Unexpected token type, %#v.", tok.TokenType)
+ }
+ scope := tok.Extra("scope")
+ if scope != "user" {
+ t.Errorf("Unexpected value for scope: %v", scope)
+ }
+}
+
+func TestExchangeRequest_JSONResponse(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.String() != "/token" {
+ t.Errorf("Unexpected exchange request URL, %v is found.", r.URL)
+ }
+ headerAuth := r.Header.Get("Authorization")
+ if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" {
+ t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
+ }
+ headerContentType := r.Header.Get("Content-Type")
+ if headerContentType != "application/x-www-form-urlencoded" {
+ t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
+ }
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ t.Errorf("Failed reading request body: %s.", err)
+ }
+ if string(body) != "code=exchange-code&grant_type=authorization_code&redirect_uri=REDIRECT_URL" {
+ t.Errorf("Unexpected exchange payload, %v is found.", string(body))
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{"access_token": "90d64460d14870c08c81352a05dedd3465940a7c", "scope": "user", "token_type": "bearer", "expires_in": 86400}`))
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ tok, err := conf.Exchange(context.Background(), "exchange-code")
+ if err != nil {
+ t.Error(err)
+ }
+ if !tok.Valid() {
+ t.Fatalf("Token invalid. Got: %#v", tok)
+ }
+ if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" {
+ t.Errorf("Unexpected access token, %#v.", tok.AccessToken)
+ }
+ if tok.TokenType != "bearer" {
+ t.Errorf("Unexpected token type, %#v.", tok.TokenType)
+ }
+ scope := tok.Extra("scope")
+ if scope != "user" {
+ t.Errorf("Unexpected value for scope: %v", scope)
+ }
+ expiresIn := tok.Extra("expires_in")
+ if expiresIn != float64(86400) {
+ t.Errorf("Unexpected non-numeric value for expires_in: %v", expiresIn)
+ }
+}
+
+func TestExtraValueRetrieval(t *testing.T) {
+ values := url.Values{}
+ kvmap := map[string]string{
+ "scope": "user", "token_type": "bearer", "expires_in": "86400.92",
+ "server_time": "1443571905.5606415", "referer_ip": "10.0.0.1",
+ "etag": "\"afZYj912P4alikMz_P11982\"", "request_id": "86400",
+ "untrimmed": " untrimmed ",
+ }
+ for key, value := range kvmap {
+ values.Set(key, value)
+ }
+
+ tok := Token{raw: values}
+ scope := tok.Extra("scope")
+ if got, want := scope, "user"; got != want {
+ t.Errorf("got scope = %q; want %q", got, want)
+ }
+ serverTime := tok.Extra("server_time")
+ if got, want := serverTime, 1443571905.5606415; got != want {
+ t.Errorf("got server_time value = %v; want %v", got, want)
+ }
+ refererIP := tok.Extra("referer_ip")
+ if got, want := refererIP, "10.0.0.1"; got != want {
+ t.Errorf("got referer_ip value = %v, want %v", got, want)
+ }
+ expiresIn := tok.Extra("expires_in")
+ if got, want := expiresIn, 86400.92; got != want {
+ t.Errorf("got expires_in value = %v, want %v", got, want)
+ }
+ requestID := tok.Extra("request_id")
+ if got, want := requestID, int64(86400); got != want {
+ t.Errorf("got request_id value = %v, want %v", got, want)
+ }
+ untrimmed := tok.Extra("untrimmed")
+ if got, want := untrimmed, " untrimmed "; got != want {
+ t.Errorf("got untrimmed = %q; want %q", got, want)
+ }
+}
+
+const day = 24 * time.Hour
+
+func TestExchangeRequest_JSONResponse_Expiry(t *testing.T) {
+ seconds := int32(day.Seconds())
+ for _, c := range []struct {
+ expires string
+ want bool
+ }{
+ {fmt.Sprintf(`"expires_in": %d`, seconds), true},
+ {fmt.Sprintf(`"expires_in": "%d"`, seconds), true}, // PayPal case
+ {fmt.Sprintf(`"expires": %d`, seconds), true}, // Facebook case
+ {`"expires": false`, false}, // wrong type
+ {`"expires": {}`, false}, // wrong type
+ {`"expires": "zzz"`, false}, // wrong value
+ } {
+ testExchangeRequest_JSONResponse_expiry(t, c.expires, c.want)
+ }
+}
+
+func testExchangeRequest_JSONResponse_expiry(t *testing.T, exp string, want bool) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(fmt.Sprintf(`{"access_token": "90d", "scope": "user", "token_type": "bearer", %s}`, exp)))
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ t1 := time.Now().Add(day)
+ tok, err := conf.Exchange(context.Background(), "exchange-code")
+ t2 := time.Now().Add(day)
+
+ if got := (err == nil); got != want {
+ if want {
+ t.Errorf("unexpected error: got %v", err)
+ } else {
+ t.Errorf("unexpected success")
+ }
+ }
+ if !want {
+ return
+ }
+ if !tok.Valid() {
+ t.Fatalf("Token invalid. Got: %#v", tok)
+ }
+ expiry := tok.Expiry
+ if expiry.Before(t1) || expiry.After(t2) {
+ t.Errorf("Unexpected value for Expiry: %v (shold be between %v and %v)", expiry, t1, t2)
+ }
+}
+
+func TestExchangeRequest_BadResponse(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{"scope": "user", "token_type": "bearer"}`))
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ tok, err := conf.Exchange(context.Background(), "code")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if tok.AccessToken != "" {
+ t.Errorf("Unexpected access token, %#v.", tok.AccessToken)
+ }
+}
+
+func TestExchangeRequest_BadResponseType(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{"access_token":123, "scope": "user", "token_type": "bearer"}`))
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ _, err := conf.Exchange(context.Background(), "exchange-code")
+ if err == nil {
+ t.Error("expected error from invalid access_token type")
+ }
+}
+
+func TestExchangeRequest_NonBasicAuth(t *testing.T) {
+ tr := &mockTransport{
+ rt: func(r *http.Request) (w *http.Response, err error) {
+ headerAuth := r.Header.Get("Authorization")
+ if headerAuth != "" {
+ t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
+ }
+ return nil, errors.New("no response")
+ },
+ }
+ c := &http.Client{Transport: tr}
+ conf := &Config{
+ ClientID: "CLIENT_ID",
+ Endpoint: Endpoint{
+ AuthURL: "https://accounts.google.com/auth",
+ TokenURL: "https://accounts.google.com/token",
+ },
+ }
+
+ ctx := context.WithValue(context.Background(), HTTPClient, c)
+ conf.Exchange(ctx, "code")
+}
+
+func TestPasswordCredentialsTokenRequest(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ expected := "/token"
+ if r.URL.String() != expected {
+ t.Errorf("URL = %q; want %q", r.URL, expected)
+ }
+ headerAuth := r.Header.Get("Authorization")
+ expected = "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ="
+ if headerAuth != expected {
+ t.Errorf("Authorization header = %q; want %q", headerAuth, expected)
+ }
+ headerContentType := r.Header.Get("Content-Type")
+ expected = "application/x-www-form-urlencoded"
+ if headerContentType != expected {
+ t.Errorf("Content-Type header = %q; want %q", headerContentType, expected)
+ }
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ t.Errorf("Failed reading request body: %s.", err)
+ }
+ expected = "grant_type=password&password=password1&scope=scope1+scope2&username=user1"
+ if string(body) != expected {
+ t.Errorf("res.Body = %q; want %q", string(body), expected)
+ }
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer"))
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ tok, err := conf.PasswordCredentialsToken(context.Background(), "user1", "password1")
+ if err != nil {
+ t.Error(err)
+ }
+ if !tok.Valid() {
+ t.Fatalf("Token invalid. Got: %#v", tok)
+ }
+ expected := "90d64460d14870c08c81352a05dedd3465940a7c"
+ if tok.AccessToken != expected {
+ t.Errorf("AccessToken = %q; want %q", tok.AccessToken, expected)
+ }
+ expected = "bearer"
+ if tok.TokenType != expected {
+ t.Errorf("TokenType = %q; want %q", tok.TokenType, expected)
+ }
+}
+
+func TestTokenRefreshRequest(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.String() == "/somethingelse" {
+ return
+ }
+ if r.URL.String() != "/token" {
+ t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL)
+ }
+ headerContentType := r.Header.Get("Content-Type")
+ if headerContentType != "application/x-www-form-urlencoded" {
+ t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
+ }
+ body, _ := ioutil.ReadAll(r.Body)
+ if string(body) != "grant_type=refresh_token&refresh_token=REFRESH_TOKEN" {
+ t.Errorf("Unexpected refresh token payload, %v is found.", string(body))
+ }
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ c := conf.Client(context.Background(), &Token{RefreshToken: "REFRESH_TOKEN"})
+ c.Get(ts.URL + "/somethingelse")
+}
+
+func TestFetchWithNoRefreshToken(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.String() == "/somethingelse" {
+ return
+ }
+ if r.URL.String() != "/token" {
+ t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL)
+ }
+ headerContentType := r.Header.Get("Content-Type")
+ if headerContentType != "application/x-www-form-urlencoded" {
+ t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
+ }
+ body, _ := ioutil.ReadAll(r.Body)
+ if string(body) != "client_id=CLIENT_ID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN" {
+ t.Errorf("Unexpected refresh token payload, %v is found.", string(body))
+ }
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ c := conf.Client(context.Background(), nil)
+ _, err := c.Get(ts.URL + "/somethingelse")
+ if err == nil {
+ t.Errorf("Fetch should return an error if no refresh token is set")
+ }
+}
+
+func TestRefreshToken_RefreshTokenReplacement(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{"access_token":"ACCESS_TOKEN", "scope": "user", "token_type": "bearer", "refresh_token": "NEW_REFRESH_TOKEN"}`))
+ return
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ tkr := &tokenRefresher{
+ conf: conf,
+ ctx: context.Background(),
+ refreshToken: "OLD_REFRESH_TOKEN",
+ }
+ tk, err := tkr.Token()
+ if err != nil {
+ t.Errorf("got err = %v; want none", err)
+ return
+ }
+ if tk.RefreshToken != tkr.refreshToken {
+ t.Errorf("tokenRefresher.refresh_token = %q; want %q", tkr.refreshToken, tk.RefreshToken)
+ }
+}
+
+func TestRefreshToken_RefreshTokenPreservation(t *testing.T) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write([]byte(`{"access_token":"ACCESS_TOKEN", "scope": "user", "token_type": "bearer"}`))
+ return
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+ const oldRefreshToken = "OLD_REFRESH_TOKEN"
+ tkr := &tokenRefresher{
+ conf: conf,
+ ctx: context.Background(),
+ refreshToken: oldRefreshToken,
+ }
+ _, err := tkr.Token()
+ if err != nil {
+ t.Fatalf("got err = %v; want none", err)
+ }
+ if tkr.refreshToken != oldRefreshToken {
+ t.Errorf("tokenRefresher.refreshToken = %q; want %q", tkr.refreshToken, oldRefreshToken)
+ }
+}
+
+func TestConfigClientWithToken(t *testing.T) {
+ tok := &Token{
+ AccessToken: "abc123",
+ }
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if got, want := r.Header.Get("Authorization"), fmt.Sprintf("Bearer %s", tok.AccessToken); got != want {
+ t.Errorf("Authorization header = %q; want %q", got, want)
+ }
+ return
+ }))
+ defer ts.Close()
+ conf := newConf(ts.URL)
+
+ c := conf.Client(context.Background(), tok)
+ req, err := http.NewRequest("GET", ts.URL, nil)
+ if err != nil {
+ t.Error(err)
+ }
+ _, err = c.Do(req)
+ if err != nil {
+ t.Error(err)
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go b/vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go
new file mode 100644
index 0000000..c0d093c
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package odnoklassniki provides constants for using OAuth2 to access Odnoklassniki.
+package odnoklassniki // import "golang.org/x/oauth2/odnoklassniki"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Odnoklassniki's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.odnoklassniki.ru/oauth/authorize",
+ TokenURL: "https://api.odnoklassniki.ru/oauth/token.do",
+}
diff --git a/vendor/golang.org/x/oauth2/paypal/paypal.go b/vendor/golang.org/x/oauth2/paypal/paypal.go
new file mode 100644
index 0000000..2e713c5
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/paypal/paypal.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package paypal provides constants for using OAuth2 to access PayPal.
+package paypal // import "golang.org/x/oauth2/paypal"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is PayPal's OAuth 2.0 endpoint in live (production) environment.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize",
+ TokenURL: "https://api.paypal.com/v1/identity/openidconnect/tokenservice",
+}
+
+// SandboxEndpoint is PayPal's OAuth 2.0 endpoint in sandbox (testing) environment.
+var SandboxEndpoint = oauth2.Endpoint{
+ AuthURL: "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize",
+ TokenURL: "https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice",
+}
diff --git a/vendor/golang.org/x/oauth2/slack/slack.go b/vendor/golang.org/x/oauth2/slack/slack.go
new file mode 100644
index 0000000..593d2f6
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/slack/slack.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package slack provides constants for using OAuth2 to access Slack.
+package slack // import "golang.org/x/oauth2/slack"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Slack's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://slack.com/oauth/authorize",
+ TokenURL: "https://slack.com/api/oauth.access",
+}
diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go
new file mode 100644
index 0000000..bdac1de
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/token.go
@@ -0,0 +1,158 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2
+
+import (
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context"
+ "golang.org/x/oauth2/internal"
+)
+
+// expiryDelta determines how earlier a token should be considered
+// expired than its actual expiration time. It is used to avoid late
+// expirations due to client-server time mismatches.
+const expiryDelta = 10 * time.Second
+
+// Token represents the credentials used to authorize
+// the requests to access protected resources on the OAuth 2.0
+// provider's backend.
+//
+// Most users of this package should not access fields of Token
+// directly. They're exported mostly for use by related packages
+// implementing derivative OAuth2 flows.
+type Token struct {
+ // AccessToken is the token that authorizes and authenticates
+ // the requests.
+ AccessToken string `json:"access_token"`
+
+ // TokenType is the type of token.
+ // The Type method returns either this or "Bearer", the default.
+ TokenType string `json:"token_type,omitempty"`
+
+ // RefreshToken is a token that's used by the application
+ // (as opposed to the user) to refresh the access token
+ // if it expires.
+ RefreshToken string `json:"refresh_token,omitempty"`
+
+ // Expiry is the optional expiration time of the access token.
+ //
+ // If zero, TokenSource implementations will reuse the same
+ // token forever and RefreshToken or equivalent
+ // mechanisms for that TokenSource will not be used.
+ Expiry time.Time `json:"expiry,omitempty"`
+
+ // raw optionally contains extra metadata from the server
+ // when updating a token.
+ raw interface{}
+}
+
+// Type returns t.TokenType if non-empty, else "Bearer".
+func (t *Token) Type() string {
+ if strings.EqualFold(t.TokenType, "bearer") {
+ return "Bearer"
+ }
+ if strings.EqualFold(t.TokenType, "mac") {
+ return "MAC"
+ }
+ if strings.EqualFold(t.TokenType, "basic") {
+ return "Basic"
+ }
+ if t.TokenType != "" {
+ return t.TokenType
+ }
+ return "Bearer"
+}
+
+// SetAuthHeader sets the Authorization header to r using the access
+// token in t.
+//
+// This method is unnecessary when using Transport or an HTTP Client
+// returned by this package.
+func (t *Token) SetAuthHeader(r *http.Request) {
+ r.Header.Set("Authorization", t.Type()+" "+t.AccessToken)
+}
+
+// WithExtra returns a new Token that's a clone of t, but using the
+// provided raw extra map. This is only intended for use by packages
+// implementing derivative OAuth2 flows.
+func (t *Token) WithExtra(extra interface{}) *Token {
+ t2 := new(Token)
+ *t2 = *t
+ t2.raw = extra
+ return t2
+}
+
+// Extra returns an extra field.
+// Extra fields are key-value pairs returned by the server as a
+// part of the token retrieval response.
+func (t *Token) Extra(key string) interface{} {
+ if raw, ok := t.raw.(map[string]interface{}); ok {
+ return raw[key]
+ }
+
+ vals, ok := t.raw.(url.Values)
+ if !ok {
+ return nil
+ }
+
+ v := vals.Get(key)
+ switch s := strings.TrimSpace(v); strings.Count(s, ".") {
+ case 0: // Contains no "."; try to parse as int
+ if i, err := strconv.ParseInt(s, 10, 64); err == nil {
+ return i
+ }
+ case 1: // Contains a single "."; try to parse as float
+ if f, err := strconv.ParseFloat(s, 64); err == nil {
+ return f
+ }
+ }
+
+ return v
+}
+
+// expired reports whether the token is expired.
+// t must be non-nil.
+func (t *Token) expired() bool {
+ if t.Expiry.IsZero() {
+ return false
+ }
+ return t.Expiry.Add(-expiryDelta).Before(time.Now())
+}
+
+// Valid reports whether t is non-nil, has an AccessToken, and is not expired.
+func (t *Token) Valid() bool {
+ return t != nil && t.AccessToken != "" && !t.expired()
+}
+
+// tokenFromInternal maps an *internal.Token struct into
+// a *Token struct.
+func tokenFromInternal(t *internal.Token) *Token {
+ if t == nil {
+ return nil
+ }
+ return &Token{
+ AccessToken: t.AccessToken,
+ TokenType: t.TokenType,
+ RefreshToken: t.RefreshToken,
+ Expiry: t.Expiry,
+ raw: t.Raw,
+ }
+}
+
+// retrieveToken takes a *Config and uses that to retrieve an *internal.Token.
+// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along
+// with an error..
+func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) {
+ tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v)
+ if err != nil {
+ return nil, err
+ }
+ return tokenFromInternal(tk), nil
+}
diff --git a/vendor/golang.org/x/oauth2/token_test.go b/vendor/golang.org/x/oauth2/token_test.go
new file mode 100644
index 0000000..80db83c
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/token_test.go
@@ -0,0 +1,72 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2
+
+import (
+ "testing"
+ "time"
+)
+
+func TestTokenExtra(t *testing.T) {
+ type testCase struct {
+ key string
+ val interface{}
+ want interface{}
+ }
+ const key = "extra-key"
+ cases := []testCase{
+ {key: key, val: "abc", want: "abc"},
+ {key: key, val: 123, want: 123},
+ {key: key, val: "", want: ""},
+ {key: "other-key", val: "def", want: nil},
+ }
+ for _, tc := range cases {
+ extra := make(map[string]interface{})
+ extra[tc.key] = tc.val
+ tok := &Token{raw: extra}
+ if got, want := tok.Extra(key), tc.want; got != want {
+ t.Errorf("Extra(%q) = %q; want %q", key, got, want)
+ }
+ }
+}
+
+func TestTokenExpiry(t *testing.T) {
+ now := time.Now()
+ cases := []struct {
+ name string
+ tok *Token
+ want bool
+ }{
+ {name: "12 seconds", tok: &Token{Expiry: now.Add(12 * time.Second)}, want: false},
+ {name: "10 seconds", tok: &Token{Expiry: now.Add(expiryDelta)}, want: true},
+ {name: "-1 hour", tok: &Token{Expiry: now.Add(-1 * time.Hour)}, want: true},
+ }
+ for _, tc := range cases {
+ if got, want := tc.tok.expired(), tc.want; got != want {
+ t.Errorf("expired (%q) = %v; want %v", tc.name, got, want)
+ }
+ }
+}
+
+func TestTokenTypeMethod(t *testing.T) {
+ cases := []struct {
+ name string
+ tok *Token
+ want string
+ }{
+ {name: "bearer-mixed_case", tok: &Token{TokenType: "beAREr"}, want: "Bearer"},
+ {name: "default-bearer", tok: &Token{}, want: "Bearer"},
+ {name: "basic", tok: &Token{TokenType: "basic"}, want: "Basic"},
+ {name: "basic-capitalized", tok: &Token{TokenType: "Basic"}, want: "Basic"},
+ {name: "mac", tok: &Token{TokenType: "mac"}, want: "MAC"},
+ {name: "mac-caps", tok: &Token{TokenType: "MAC"}, want: "MAC"},
+ {name: "mac-mixed_case", tok: &Token{TokenType: "mAc"}, want: "MAC"},
+ }
+ for _, tc := range cases {
+ if got, want := tc.tok.Type(), tc.want; got != want {
+ t.Errorf("TokenType(%q) = %v; want %v", tc.name, got, want)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go
new file mode 100644
index 0000000..92ac7e2
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/transport.go
@@ -0,0 +1,132 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2
+
+import (
+ "errors"
+ "io"
+ "net/http"
+ "sync"
+)
+
+// Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
+// wrapping a base RoundTripper and adding an Authorization header
+// with a token from the supplied Sources.
+//
+// Transport is a low-level mechanism. Most code will use the
+// higher-level Config.Client method instead.
+type Transport struct {
+ // Source supplies the token to add to outgoing requests'
+ // Authorization headers.
+ Source TokenSource
+
+ // Base is the base RoundTripper used to make HTTP requests.
+ // If nil, http.DefaultTransport is used.
+ Base http.RoundTripper
+
+ mu sync.Mutex // guards modReq
+ modReq map[*http.Request]*http.Request // original -> modified
+}
+
+// RoundTrip authorizes and authenticates the request with an
+// access token. If no token exists or token is expired,
+// tries to refresh/fetch a new token.
+func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
+ if t.Source == nil {
+ return nil, errors.New("oauth2: Transport's Source is nil")
+ }
+ token, err := t.Source.Token()
+ if err != nil {
+ return nil, err
+ }
+
+ req2 := cloneRequest(req) // per RoundTripper contract
+ token.SetAuthHeader(req2)
+ t.setModReq(req, req2)
+ res, err := t.base().RoundTrip(req2)
+ if err != nil {
+ t.setModReq(req, nil)
+ return nil, err
+ }
+ res.Body = &onEOFReader{
+ rc: res.Body,
+ fn: func() { t.setModReq(req, nil) },
+ }
+ return res, nil
+}
+
+// CancelRequest cancels an in-flight request by closing its connection.
+func (t *Transport) CancelRequest(req *http.Request) {
+ type canceler interface {
+ CancelRequest(*http.Request)
+ }
+ if cr, ok := t.base().(canceler); ok {
+ t.mu.Lock()
+ modReq := t.modReq[req]
+ delete(t.modReq, req)
+ t.mu.Unlock()
+ cr.CancelRequest(modReq)
+ }
+}
+
+func (t *Transport) base() http.RoundTripper {
+ if t.Base != nil {
+ return t.Base
+ }
+ return http.DefaultTransport
+}
+
+func (t *Transport) setModReq(orig, mod *http.Request) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.modReq == nil {
+ t.modReq = make(map[*http.Request]*http.Request)
+ }
+ if mod == nil {
+ delete(t.modReq, orig)
+ } else {
+ t.modReq[orig] = mod
+ }
+}
+
+// cloneRequest returns a clone of the provided *http.Request.
+// The clone is a shallow copy of the struct and its Header map.
+func cloneRequest(r *http.Request) *http.Request {
+ // shallow copy of the struct
+ r2 := new(http.Request)
+ *r2 = *r
+ // deep copy of the Header
+ r2.Header = make(http.Header, len(r.Header))
+ for k, s := range r.Header {
+ r2.Header[k] = append([]string(nil), s...)
+ }
+ return r2
+}
+
+type onEOFReader struct {
+ rc io.ReadCloser
+ fn func()
+}
+
+func (r *onEOFReader) Read(p []byte) (n int, err error) {
+ n, err = r.rc.Read(p)
+ if err == io.EOF {
+ r.runFunc()
+ }
+ return
+}
+
+func (r *onEOFReader) Close() error {
+ err := r.rc.Close()
+ r.runFunc()
+ return err
+}
+
+func (r *onEOFReader) runFunc() {
+ if fn := r.fn; fn != nil {
+ fn()
+ r.fn = nil
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/transport_test.go b/vendor/golang.org/x/oauth2/transport_test.go
new file mode 100644
index 0000000..d6e8087
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/transport_test.go
@@ -0,0 +1,108 @@
+package oauth2
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+ "time"
+)
+
+type tokenSource struct{ token *Token }
+
+func (t *tokenSource) Token() (*Token, error) {
+ return t.token, nil
+}
+
+func TestTransportNilTokenSource(t *testing.T) {
+ tr := &Transport{}
+ server := newMockServer(func(w http.ResponseWriter, r *http.Request) {})
+ defer server.Close()
+ client := &http.Client{Transport: tr}
+ resp, err := client.Get(server.URL)
+ if err == nil {
+ t.Errorf("got no errors, want an error with nil token source")
+ }
+ if resp != nil {
+ t.Errorf("Response = %v; want nil", resp)
+ }
+}
+
+func TestTransportTokenSource(t *testing.T) {
+ ts := &tokenSource{
+ token: &Token{
+ AccessToken: "abc",
+ },
+ }
+ tr := &Transport{
+ Source: ts,
+ }
+ server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
+ if got, want := r.Header.Get("Authorization"), "Bearer abc"; got != want {
+ t.Errorf("Authorization header = %q; want %q", got, want)
+ }
+ })
+ defer server.Close()
+ client := &http.Client{Transport: tr}
+ res, err := client.Get(server.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+}
+
+// Test for case-sensitive token types, per https://github.com/golang/oauth2/issues/113
+func TestTransportTokenSourceTypes(t *testing.T) {
+ const val = "abc"
+ tests := []struct {
+ key string
+ val string
+ want string
+ }{
+ {key: "bearer", val: val, want: "Bearer abc"},
+ {key: "mac", val: val, want: "MAC abc"},
+ {key: "basic", val: val, want: "Basic abc"},
+ }
+ for _, tc := range tests {
+ ts := &tokenSource{
+ token: &Token{
+ AccessToken: tc.val,
+ TokenType: tc.key,
+ },
+ }
+ tr := &Transport{
+ Source: ts,
+ }
+ server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
+ if got, want := r.Header.Get("Authorization"), tc.want; got != want {
+ t.Errorf("Authorization header (%q) = %q; want %q", val, got, want)
+ }
+ })
+ defer server.Close()
+ client := &http.Client{Transport: tr}
+ res, err := client.Get(server.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ }
+}
+
+func TestTokenValidNoAccessToken(t *testing.T) {
+ token := &Token{}
+ if token.Valid() {
+ t.Errorf("got valid with no access token; want invalid")
+ }
+}
+
+func TestExpiredWithExpiry(t *testing.T) {
+ token := &Token{
+ Expiry: time.Now().Add(-5 * time.Hour),
+ }
+ if token.Valid() {
+ t.Errorf("got valid with expired token; want invalid")
+ }
+}
+
+func newMockServer(handler func(w http.ResponseWriter, r *http.Request)) *httptest.Server {
+ return httptest.NewServer(http.HandlerFunc(handler))
+}
diff --git a/vendor/golang.org/x/oauth2/uber/uber.go b/vendor/golang.org/x/oauth2/uber/uber.go
new file mode 100644
index 0000000..5520a64
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/uber/uber.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package uber provides constants for using OAuth2 to access Uber.
+package uber // import "golang.org/x/oauth2/uber"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is Uber's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://login.uber.com/oauth/v2/authorize",
+ TokenURL: "https://login.uber.com/oauth/v2/token",
+}
diff --git a/vendor/golang.org/x/oauth2/vk/vk.go b/vendor/golang.org/x/oauth2/vk/vk.go
new file mode 100644
index 0000000..bd8e159
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/vk/vk.go
@@ -0,0 +1,16 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vk provides constants for using OAuth2 to access VK.com.
+package vk // import "golang.org/x/oauth2/vk"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is VK's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://oauth.vk.com/authorize",
+ TokenURL: "https://oauth.vk.com/access_token",
+}
diff --git a/vendor/golang.org/x/oauth2/yandex/yandex.go b/vendor/golang.org/x/oauth2/yandex/yandex.go
new file mode 100644
index 0000000..5ebf666
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/yandex/yandex.go
@@ -0,0 +1,16 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package yandex provides constants for using OAuth2 to access Yandex APIs.
+package yandex // import "golang.org/x/oauth2/yandex"
+
+import (
+ "golang.org/x/oauth2"
+)
+
+// Endpoint is the Yandex OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://oauth.yandex.com/authorize",
+ TokenURL: "https://oauth.yandex.com/token",
+}
diff --git a/vendor/golang.org/x/sys/unix/dev_darwin_test.go b/vendor/golang.org/x/sys/unix/dev_darwin_test.go
index 48d0448..bf1adf3 100644
--- a/vendor/golang.org/x/sys/unix/dev_darwin_test.go
+++ b/vendor/golang.org/x/sys/unix/dev_darwin_test.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build go1.7
+
package unix_test
import (
diff --git a/vendor/golang.org/x/sys/unix/dev_dragonfly_test.go b/vendor/golang.org/x/sys/unix/dev_dragonfly_test.go
index 2caba08..9add376 100644
--- a/vendor/golang.org/x/sys/unix/dev_dragonfly_test.go
+++ b/vendor/golang.org/x/sys/unix/dev_dragonfly_test.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build go1.7
+
package unix_test
import (
diff --git a/vendor/golang.org/x/sys/unix/dev_linux_test.go b/vendor/golang.org/x/sys/unix/dev_linux_test.go
index 6e001f3..2fd3ead 100644
--- a/vendor/golang.org/x/sys/unix/dev_linux_test.go
+++ b/vendor/golang.org/x/sys/unix/dev_linux_test.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build go1.7
+
package unix_test
import (
diff --git a/vendor/golang.org/x/sys/unix/dev_netbsd_test.go b/vendor/golang.org/x/sys/unix/dev_netbsd_test.go
index c39a80a..24a7e17 100644
--- a/vendor/golang.org/x/sys/unix/dev_netbsd_test.go
+++ b/vendor/golang.org/x/sys/unix/dev_netbsd_test.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build go1.7
+
package unix_test
import (
diff --git a/vendor/golang.org/x/sys/unix/dev_openbsd_test.go b/vendor/golang.org/x/sys/unix/dev_openbsd_test.go
index 5635d27..e6cb64f 100644
--- a/vendor/golang.org/x/sys/unix/dev_openbsd_test.go
+++ b/vendor/golang.org/x/sys/unix/dev_openbsd_test.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build go1.7
+
package unix_test
import (
diff --git a/vendor/golang.org/x/sys/unix/dev_solaris_test.go b/vendor/golang.org/x/sys/unix/dev_solaris_test.go
index db58c0d..656508c 100644
--- a/vendor/golang.org/x/sys/unix/dev_solaris_test.go
+++ b/vendor/golang.org/x/sys/unix/dev_solaris_test.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build go1.7
+
package unix_test
import (
diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go
index 47ab664..faae207 100644
--- a/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go
+++ b/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go
@@ -60,3 +60,7 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
+
+// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
+// of darwin/arm the syscall is called sysctl instead of __sysctl.
+const SYS___SYSCTL = SYS_SYSCTL
diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go
index 78b714c..52c2037 100644
--- a/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/vendor/golang.org/x/sys/windows/types_windows.go
@@ -159,9 +159,6 @@ const (
WAIT_OBJECT_0 = 0x00000000
WAIT_FAILED = 0xFFFFFFFF
- CREATE_NEW_PROCESS_GROUP = 0x00000200
- CREATE_UNICODE_ENVIRONMENT = 0x00000400
-
PROCESS_TERMINATE = 1
PROCESS_QUERY_INFORMATION = 0x00000400
SYNCHRONIZE = 0x00100000
@@ -179,6 +176,26 @@ const (
)
const (
+ // Process creation flags.
+ CREATE_BREAKAWAY_FROM_JOB = 0x01000000
+ CREATE_DEFAULT_ERROR_MODE = 0x04000000
+ CREATE_NEW_CONSOLE = 0x00000010
+ CREATE_NEW_PROCESS_GROUP = 0x00000200
+ CREATE_NO_WINDOW = 0x08000000
+ CREATE_PROTECTED_PROCESS = 0x00040000
+ CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000
+ CREATE_SEPARATE_WOW_VDM = 0x00000800
+ CREATE_SHARED_WOW_VDM = 0x00001000
+ CREATE_SUSPENDED = 0x00000004
+ CREATE_UNICODE_ENVIRONMENT = 0x00000400
+ DEBUG_ONLY_THIS_PROCESS = 0x00000002
+ DEBUG_PROCESS = 0x00000001
+ DETACHED_PROCESS = 0x00000008
+ EXTENDED_STARTUPINFO_PRESENT = 0x00080000
+ INHERIT_PARENT_AFFINITY = 0x00010000
+)
+
+const (
// flags for CreateToolhelp32Snapshot
TH32CS_SNAPHEAPLIST = 0x01
TH32CS_SNAPPROCESS = 0x02