github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/golang.org/x/oauth2/google/google.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package google provides support for making OAuth2 authorized and 6 // authenticated HTTP requests to Google APIs. 7 // It supports the Web server flow, client-side credentials, service accounts, 8 // Google Compute Engine service accounts, and Google App Engine service 9 // accounts. 10 // 11 // For more information, please read 12 // https://developers.google.com/accounts/docs/OAuth2 13 // and 14 // https://developers.google.com/accounts/docs/application-default-credentials. 15 package google 16 17 import ( 18 "encoding/json" 19 "errors" 20 "fmt" 21 "strings" 22 "time" 23 24 "golang.org/x/oauth2" 25 "golang.org/x/oauth2/jwt" 26 "google.golang.org/cloud/compute/metadata" 27 ) 28 29 // Endpoint is Google's OAuth 2.0 endpoint. 30 var Endpoint = oauth2.Endpoint{ 31 AuthURL: "https://accounts.google.com/o/oauth2/auth", 32 TokenURL: "https://accounts.google.com/o/oauth2/token", 33 } 34 35 // JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow. 36 const JWTTokenURL = "https://accounts.google.com/o/oauth2/token" 37 38 // ConfigFromJSON uses a Google Developers Console client_credentials.json 39 // file to construct a config. 40 // client_credentials.json can be downloadable from https://console.developers.google.com, 41 // under "APIs & Auth" > "Credentials". Download the Web application credentials in the 42 // JSON format and provide the contents of the file as jsonKey. 43 func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) { 44 type cred struct { 45 ClientID string `json:"client_id"` 46 ClientSecret string `json:"client_secret"` 47 RedirectURIs []string `json:"redirect_uris"` 48 AuthURI string `json:"auth_uri"` 49 TokenURI string `json:"token_uri"` 50 } 51 var j struct { 52 Web *cred `json:"web"` 53 Installed *cred `json:"installed"` 54 } 55 if err := json.Unmarshal(jsonKey, &j); err != nil { 56 return nil, err 57 } 58 var c *cred 59 switch { 60 case j.Web != nil: 61 c = j.Web 62 case j.Installed != nil: 63 c = j.Installed 64 default: 65 return nil, fmt.Errorf("oauth2/google: no credentials found") 66 } 67 if len(c.RedirectURIs) < 1 { 68 return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json") 69 } 70 return &oauth2.Config{ 71 ClientID: c.ClientID, 72 ClientSecret: c.ClientSecret, 73 RedirectURL: c.RedirectURIs[0], 74 Scopes: scope, 75 Endpoint: oauth2.Endpoint{ 76 AuthURL: c.AuthURI, 77 TokenURL: c.TokenURI, 78 }, 79 }, nil 80 } 81 82 // JWTConfigFromJSON uses a Google Developers service account JSON key file to read 83 // the credentials that authorize and authenticate the requests. 84 // Create a service account on "Credentials" page under "APIs & Auth" for your 85 // project at https://console.developers.google.com to download a JSON key file. 86 func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) { 87 var key struct { 88 Email string `json:"client_email"` 89 PrivateKey string `json:"private_key"` 90 } 91 if err := json.Unmarshal(jsonKey, &key); err != nil { 92 return nil, err 93 } 94 return &jwt.Config{ 95 Email: key.Email, 96 PrivateKey: []byte(key.PrivateKey), 97 Scopes: scope, 98 TokenURL: JWTTokenURL, 99 }, nil 100 } 101 102 // ComputeTokenSource returns a token source that fetches access tokens 103 // from Google Compute Engine (GCE)'s metadata server. It's only valid to use 104 // this token source if your program is running on a GCE instance. 105 // If no account is specified, "default" is used. 106 // Further information about retrieving access tokens from the GCE metadata 107 // server can be found at https://cloud.google.com/compute/docs/authentication. 108 func ComputeTokenSource(account string) oauth2.TokenSource { 109 return oauth2.ReuseTokenSource(nil, computeSource{account: account}) 110 } 111 112 type computeSource struct { 113 account string 114 } 115 116 func (cs computeSource) Token() (*oauth2.Token, error) { 117 if !metadata.OnGCE() { 118 return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE") 119 } 120 acct := cs.account 121 if acct == "" { 122 acct = "default" 123 } 124 tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token") 125 if err != nil { 126 return nil, err 127 } 128 var res struct { 129 AccessToken string `json:"access_token"` 130 ExpiresInSec int `json:"expires_in"` 131 TokenType string `json:"token_type"` 132 } 133 err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res) 134 if err != nil { 135 return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err) 136 } 137 if res.ExpiresInSec == 0 || res.AccessToken == "" { 138 return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata") 139 } 140 return &oauth2.Token{ 141 AccessToken: res.AccessToken, 142 TokenType: res.TokenType, 143 Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second), 144 }, nil 145 }