github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/golang.org/x/oauth2/google/default.go (about) 1 // Copyright 2015 The oauth2 Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package google 6 7 import ( 8 "encoding/json" 9 "errors" 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 "os" 14 "path/filepath" 15 "runtime" 16 17 "golang.org/x/net/context" 18 "golang.org/x/oauth2" 19 "golang.org/x/oauth2/jwt" 20 "google.golang.org/cloud/compute/metadata" 21 ) 22 23 // DefaultClient returns an HTTP Client that uses the 24 // DefaultTokenSource to obtain authentication credentials. 25 // 26 // This client should be used when developing services 27 // that run on Google App Engine or Google Compute Engine 28 // and use "Application Default Credentials." 29 // 30 // For more details, see: 31 // https://developers.google.com/accounts/docs/application-default-credentials 32 // 33 func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) { 34 ts, err := DefaultTokenSource(ctx, scope...) 35 if err != nil { 36 return nil, err 37 } 38 return oauth2.NewClient(ctx, ts), nil 39 } 40 41 // DefaultTokenSource is a token source that uses 42 // "Application Default Credentials". 43 // 44 // It looks for credentials in the following places, 45 // preferring the first location found: 46 // 47 // 1. A JSON file whose path is specified by the 48 // GOOGLE_APPLICATION_CREDENTIALS environment variable. 49 // 2. A JSON file in a location known to the gcloud command-line tool. 50 // On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. 51 // On other systems, $HOME/.config/gcloud/application_default_credentials.json. 52 // 3. On Google App Engine it uses the appengine.AccessToken function. 53 // 4. On Google Compute Engine, it fetches credentials from the metadata server. 54 // (In this final case any provided scopes are ignored.) 55 // 56 // For more details, see: 57 // https://developers.google.com/accounts/docs/application-default-credentials 58 // 59 func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) { 60 // First, try the environment variable. 61 const envVar = "GOOGLE_APPLICATION_CREDENTIALS" 62 if filename := os.Getenv(envVar); filename != "" { 63 ts, err := tokenSourceFromFile(ctx, filename, scope) 64 if err != nil { 65 return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err) 66 } 67 return ts, nil 68 } 69 70 // Second, try a well-known file. 71 filename := wellKnownFile() 72 _, err := os.Stat(filename) 73 if err == nil { 74 ts, err2 := tokenSourceFromFile(ctx, filename, scope) 75 if err2 == nil { 76 return ts, nil 77 } 78 err = err2 79 } else if os.IsNotExist(err) { 80 err = nil // ignore this error 81 } 82 if err != nil { 83 return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err) 84 } 85 86 // Third, if we're on Google App Engine use those credentials. 87 if appengineTokenFunc != nil { 88 return AppEngineTokenSource(ctx, scope...), nil 89 } 90 91 // Fourth, if we're on Google Compute Engine use the metadata server. 92 if metadata.OnGCE() { 93 return ComputeTokenSource(""), nil 94 } 95 96 // None are found; return helpful error. 97 const url = "https://developers.google.com/accounts/docs/application-default-credentials" 98 return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url) 99 } 100 101 func wellKnownFile() string { 102 const f = "application_default_credentials.json" 103 if runtime.GOOS == "windows" { 104 return filepath.Join(os.Getenv("APPDATA"), "gcloud", f) 105 } 106 return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f) 107 } 108 109 func tokenSourceFromFile(ctx context.Context, filename string, scopes []string) (oauth2.TokenSource, error) { 110 b, err := ioutil.ReadFile(filename) 111 if err != nil { 112 return nil, err 113 } 114 var d struct { 115 // Common fields 116 Type string 117 ClientID string `json:"client_id"` 118 119 // User Credential fields 120 ClientSecret string `json:"client_secret"` 121 RefreshToken string `json:"refresh_token"` 122 123 // Service Account fields 124 ClientEmail string `json:"client_email"` 125 PrivateKeyID string `json:"private_key_id"` 126 PrivateKey string `json:"private_key"` 127 } 128 if err := json.Unmarshal(b, &d); err != nil { 129 return nil, err 130 } 131 switch d.Type { 132 case "authorized_user": 133 cfg := &oauth2.Config{ 134 ClientID: d.ClientID, 135 ClientSecret: d.ClientSecret, 136 Scopes: append([]string{}, scopes...), // copy 137 Endpoint: Endpoint, 138 } 139 tok := &oauth2.Token{RefreshToken: d.RefreshToken} 140 return cfg.TokenSource(ctx, tok), nil 141 case "service_account": 142 cfg := &jwt.Config{ 143 Email: d.ClientEmail, 144 PrivateKey: []byte(d.PrivateKey), 145 Scopes: append([]string{}, scopes...), // copy 146 TokenURL: JWTTokenURL, 147 } 148 return cfg.TokenSource(ctx), nil 149 case "": 150 return nil, errors.New("missing 'type' field in credentials") 151 default: 152 return nil, fmt.Errorf("unknown credential type: %q", d.Type) 153 } 154 }