diff options
Diffstat (limited to 'vendor/golang.org/x/oauth2/google/google.go')
-rw-r--r-- | vendor/golang.org/x/oauth2/google/google.go | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/vendor/golang.org/x/oauth2/google/google.go b/vendor/golang.org/x/oauth2/google/google.go new file mode 100644 index 0000000..4b0b547 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/google.go | |||
@@ -0,0 +1,193 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package google | ||
6 | |||
7 | import ( | ||
8 | "context" | ||
9 | "encoding/json" | ||
10 | "errors" | ||
11 | "fmt" | ||
12 | "strings" | ||
13 | "time" | ||
14 | |||
15 | "cloud.google.com/go/compute/metadata" | ||
16 | "golang.org/x/oauth2" | ||
17 | "golang.org/x/oauth2/jwt" | ||
18 | ) | ||
19 | |||
20 | // Endpoint is Google's OAuth 2.0 endpoint. | ||
21 | var Endpoint = oauth2.Endpoint{ | ||
22 | AuthURL: "https://accounts.google.com/o/oauth2/auth", | ||
23 | TokenURL: "https://accounts.google.com/o/oauth2/token", | ||
24 | AuthStyle: oauth2.AuthStyleInParams, | ||
25 | } | ||
26 | |||
27 | // JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow. | ||
28 | const JWTTokenURL = "https://accounts.google.com/o/oauth2/token" | ||
29 | |||
30 | // ConfigFromJSON uses a Google Developers Console client_credentials.json | ||
31 | // file to construct a config. | ||
32 | // client_credentials.json can be downloaded from | ||
33 | // https://console.developers.google.com, under "Credentials". Download the Web | ||
34 | // application credentials in the JSON format and provide the contents of the | ||
35 | // file as jsonKey. | ||
36 | func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) { | ||
37 | type cred struct { | ||
38 | ClientID string `json:"client_id"` | ||
39 | ClientSecret string `json:"client_secret"` | ||
40 | RedirectURIs []string `json:"redirect_uris"` | ||
41 | AuthURI string `json:"auth_uri"` | ||
42 | TokenURI string `json:"token_uri"` | ||
43 | } | ||
44 | var j struct { | ||
45 | Web *cred `json:"web"` | ||
46 | Installed *cred `json:"installed"` | ||
47 | } | ||
48 | if err := json.Unmarshal(jsonKey, &j); err != nil { | ||
49 | return nil, err | ||
50 | } | ||
51 | var c *cred | ||
52 | switch { | ||
53 | case j.Web != nil: | ||
54 | c = j.Web | ||
55 | case j.Installed != nil: | ||
56 | c = j.Installed | ||
57 | default: | ||
58 | return nil, fmt.Errorf("oauth2/google: no credentials found") | ||
59 | } | ||
60 | if len(c.RedirectURIs) < 1 { | ||
61 | return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json") | ||
62 | } | ||
63 | return &oauth2.Config{ | ||
64 | ClientID: c.ClientID, | ||
65 | ClientSecret: c.ClientSecret, | ||
66 | RedirectURL: c.RedirectURIs[0], | ||
67 | Scopes: scope, | ||
68 | Endpoint: oauth2.Endpoint{ | ||
69 | AuthURL: c.AuthURI, | ||
70 | TokenURL: c.TokenURI, | ||
71 | }, | ||
72 | }, nil | ||
73 | } | ||
74 | |||
75 | // JWTConfigFromJSON uses a Google Developers service account JSON key file to read | ||
76 | // the credentials that authorize and authenticate the requests. | ||
77 | // Create a service account on "Credentials" for your project at | ||
78 | // https://console.developers.google.com to download a JSON key file. | ||
79 | func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) { | ||
80 | var f credentialsFile | ||
81 | if err := json.Unmarshal(jsonKey, &f); err != nil { | ||
82 | return nil, err | ||
83 | } | ||
84 | if f.Type != serviceAccountKey { | ||
85 | return nil, fmt.Errorf("google: read JWT from JSON credentials: 'type' field is %q (expected %q)", f.Type, serviceAccountKey) | ||
86 | } | ||
87 | scope = append([]string(nil), scope...) // copy | ||
88 | return f.jwtConfig(scope), nil | ||
89 | } | ||
90 | |||
91 | // JSON key file types. | ||
92 | const ( | ||
93 | serviceAccountKey = "service_account" | ||
94 | userCredentialsKey = "authorized_user" | ||
95 | ) | ||
96 | |||
97 | // credentialsFile is the unmarshalled representation of a credentials file. | ||
98 | type credentialsFile struct { | ||
99 | Type string `json:"type"` // serviceAccountKey or userCredentialsKey | ||
100 | |||
101 | // Service Account fields | ||
102 | ClientEmail string `json:"client_email"` | ||
103 | PrivateKeyID string `json:"private_key_id"` | ||
104 | PrivateKey string `json:"private_key"` | ||
105 | TokenURL string `json:"token_uri"` | ||
106 | ProjectID string `json:"project_id"` | ||
107 | |||
108 | // User Credential fields | ||
109 | // (These typically come from gcloud auth.) | ||
110 | ClientSecret string `json:"client_secret"` | ||
111 | ClientID string `json:"client_id"` | ||
112 | RefreshToken string `json:"refresh_token"` | ||
113 | } | ||
114 | |||
115 | func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config { | ||
116 | cfg := &jwt.Config{ | ||
117 | Email: f.ClientEmail, | ||
118 | PrivateKey: []byte(f.PrivateKey), | ||
119 | PrivateKeyID: f.PrivateKeyID, | ||
120 | Scopes: scopes, | ||
121 | TokenURL: f.TokenURL, | ||
122 | } | ||
123 | if cfg.TokenURL == "" { | ||
124 | cfg.TokenURL = JWTTokenURL | ||
125 | } | ||
126 | return cfg | ||
127 | } | ||
128 | |||
129 | func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oauth2.TokenSource, error) { | ||
130 | switch f.Type { | ||
131 | case serviceAccountKey: | ||
132 | cfg := f.jwtConfig(scopes) | ||
133 | return cfg.TokenSource(ctx), nil | ||
134 | case userCredentialsKey: | ||
135 | cfg := &oauth2.Config{ | ||
136 | ClientID: f.ClientID, | ||
137 | ClientSecret: f.ClientSecret, | ||
138 | Scopes: scopes, | ||
139 | Endpoint: Endpoint, | ||
140 | } | ||
141 | tok := &oauth2.Token{RefreshToken: f.RefreshToken} | ||
142 | return cfg.TokenSource(ctx, tok), nil | ||
143 | case "": | ||
144 | return nil, errors.New("missing 'type' field in credentials") | ||
145 | default: | ||
146 | return nil, fmt.Errorf("unknown credential type: %q", f.Type) | ||
147 | } | ||
148 | } | ||
149 | |||
150 | // ComputeTokenSource returns a token source that fetches access tokens | ||
151 | // from Google Compute Engine (GCE)'s metadata server. It's only valid to use | ||
152 | // this token source if your program is running on a GCE instance. | ||
153 | // If no account is specified, "default" is used. | ||
154 | // Further information about retrieving access tokens from the GCE metadata | ||
155 | // server can be found at https://cloud.google.com/compute/docs/authentication. | ||
156 | func ComputeTokenSource(account string) oauth2.TokenSource { | ||
157 | return oauth2.ReuseTokenSource(nil, computeSource{account: account}) | ||
158 | } | ||
159 | |||
160 | type computeSource struct { | ||
161 | account string | ||
162 | } | ||
163 | |||
164 | func (cs computeSource) Token() (*oauth2.Token, error) { | ||
165 | if !metadata.OnGCE() { | ||
166 | return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE") | ||
167 | } | ||
168 | acct := cs.account | ||
169 | if acct == "" { | ||
170 | acct = "default" | ||
171 | } | ||
172 | tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token") | ||
173 | if err != nil { | ||
174 | return nil, err | ||
175 | } | ||
176 | var res struct { | ||
177 | AccessToken string `json:"access_token"` | ||
178 | ExpiresInSec int `json:"expires_in"` | ||
179 | TokenType string `json:"token_type"` | ||
180 | } | ||
181 | err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res) | ||
182 | if err != nil { | ||
183 | return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err) | ||
184 | } | ||
185 | if res.ExpiresInSec == 0 || res.AccessToken == "" { | ||
186 | return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata") | ||
187 | } | ||
188 | return &oauth2.Token{ | ||
189 | AccessToken: res.AccessToken, | ||
190 | TokenType: res.TokenType, | ||
191 | Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second), | ||
192 | }, nil | ||
193 | } | ||