aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/golang.org/x/oauth2/google
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/oauth2/google')
-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
13 files changed, 1226 insertions, 0 deletions
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