diff options
Diffstat (limited to 'vendor/golang.org/x/oauth2/oauth2.go')
-rw-r--r-- | vendor/golang.org/x/oauth2/oauth2.go | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go new file mode 100644 index 0000000..428283f --- /dev/null +++ b/vendor/golang.org/x/oauth2/oauth2.go | |||
@@ -0,0 +1,381 @@ | |||
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 oauth2 provides support for making | ||
6 | // OAuth2 authorized and authenticated HTTP requests, | ||
7 | // as specified in RFC 6749. | ||
8 | // It can additionally grant authorization with Bearer JWT. | ||
9 | package oauth2 // import "golang.org/x/oauth2" | ||
10 | |||
11 | import ( | ||
12 | "bytes" | ||
13 | "context" | ||
14 | "errors" | ||
15 | "net/http" | ||
16 | "net/url" | ||
17 | "strings" | ||
18 | "sync" | ||
19 | |||
20 | "golang.org/x/oauth2/internal" | ||
21 | ) | ||
22 | |||
23 | // NoContext is the default context you should supply if not using | ||
24 | // your own context.Context (see https://golang.org/x/net/context). | ||
25 | // | ||
26 | // Deprecated: Use context.Background() or context.TODO() instead. | ||
27 | var NoContext = context.TODO() | ||
28 | |||
29 | // RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. | ||
30 | // | ||
31 | // Deprecated: this function no longer does anything. Caller code that | ||
32 | // wants to avoid potential extra HTTP requests made during | ||
33 | // auto-probing of the provider's auth style should set | ||
34 | // Endpoint.AuthStyle. | ||
35 | func RegisterBrokenAuthHeaderProvider(tokenURL string) {} | ||
36 | |||
37 | // Config describes a typical 3-legged OAuth2 flow, with both the | ||
38 | // client application information and the server's endpoint URLs. | ||
39 | // For the client credentials 2-legged OAuth2 flow, see the clientcredentials | ||
40 | // package (https://golang.org/x/oauth2/clientcredentials). | ||
41 | type Config struct { | ||
42 | // ClientID is the application's ID. | ||
43 | ClientID string | ||
44 | |||
45 | // ClientSecret is the application's secret. | ||
46 | ClientSecret string | ||
47 | |||
48 | // Endpoint contains the resource server's token endpoint | ||
49 | // URLs. These are constants specific to each server and are | ||
50 | // often available via site-specific packages, such as | ||
51 | // google.Endpoint or github.Endpoint. | ||
52 | Endpoint Endpoint | ||
53 | |||
54 | // RedirectURL is the URL to redirect users going through | ||
55 | // the OAuth flow, after the resource owner's URLs. | ||
56 | RedirectURL string | ||
57 | |||
58 | // Scope specifies optional requested permissions. | ||
59 | Scopes []string | ||
60 | } | ||
61 | |||
62 | // A TokenSource is anything that can return a token. | ||
63 | type TokenSource interface { | ||
64 | // Token returns a token or an error. | ||
65 | // Token must be safe for concurrent use by multiple goroutines. | ||
66 | // The returned Token must not be modified. | ||
67 | Token() (*Token, error) | ||
68 | } | ||
69 | |||
70 | // Endpoint represents an OAuth 2.0 provider's authorization and token | ||
71 | // endpoint URLs. | ||
72 | type Endpoint struct { | ||
73 | AuthURL string | ||
74 | TokenURL string | ||
75 | |||
76 | // AuthStyle optionally specifies how the endpoint wants the | ||
77 | // client ID & client secret sent. The zero value means to | ||
78 | // auto-detect. | ||
79 | AuthStyle AuthStyle | ||
80 | } | ||
81 | |||
82 | // AuthStyle represents how requests for tokens are authenticated | ||
83 | // to the server. | ||
84 | type AuthStyle int | ||
85 | |||
86 | const ( | ||
87 | // AuthStyleAutoDetect means to auto-detect which authentication | ||
88 | // style the provider wants by trying both ways and caching | ||
89 | // the successful way for the future. | ||
90 | AuthStyleAutoDetect AuthStyle = 0 | ||
91 | |||
92 | // AuthStyleInParams sends the "client_id" and "client_secret" | ||
93 | // in the POST body as application/x-www-form-urlencoded parameters. | ||
94 | AuthStyleInParams AuthStyle = 1 | ||
95 | |||
96 | // AuthStyleInHeader sends the client_id and client_password | ||
97 | // using HTTP Basic Authorization. This is an optional style | ||
98 | // described in the OAuth2 RFC 6749 section 2.3.1. | ||
99 | AuthStyleInHeader AuthStyle = 2 | ||
100 | ) | ||
101 | |||
102 | var ( | ||
103 | // AccessTypeOnline and AccessTypeOffline are options passed | ||
104 | // to the Options.AuthCodeURL method. They modify the | ||
105 | // "access_type" field that gets sent in the URL returned by | ||
106 | // AuthCodeURL. | ||
107 | // | ||
108 | // Online is the default if neither is specified. If your | ||
109 | // application needs to refresh access tokens when the user | ||
110 | // is not present at the browser, then use offline. This will | ||
111 | // result in your application obtaining a refresh token the | ||
112 | // first time your application exchanges an authorization | ||
113 | // code for a user. | ||
114 | AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online") | ||
115 | AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline") | ||
116 | |||
117 | // ApprovalForce forces the users to view the consent dialog | ||
118 | // and confirm the permissions request at the URL returned | ||
119 | // from AuthCodeURL, even if they've already done so. | ||
120 | ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force") | ||
121 | ) | ||
122 | |||
123 | // An AuthCodeOption is passed to Config.AuthCodeURL. | ||
124 | type AuthCodeOption interface { | ||
125 | setValue(url.Values) | ||
126 | } | ||
127 | |||
128 | type setParam struct{ k, v string } | ||
129 | |||
130 | func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) } | ||
131 | |||
132 | // SetAuthURLParam builds an AuthCodeOption which passes key/value parameters | ||
133 | // to a provider's authorization endpoint. | ||
134 | func SetAuthURLParam(key, value string) AuthCodeOption { | ||
135 | return setParam{key, value} | ||
136 | } | ||
137 | |||
138 | // AuthCodeURL returns a URL to OAuth 2.0 provider's consent page | ||
139 | // that asks for permissions for the required scopes explicitly. | ||
140 | // | ||
141 | // State is a token to protect the user from CSRF attacks. You must | ||
142 | // always provide a non-empty string and validate that it matches the | ||
143 | // the state query parameter on your redirect callback. | ||
144 | // See http://tools.ietf.org/html/rfc6749#section-10.12 for more info. | ||
145 | // | ||
146 | // Opts may include AccessTypeOnline or AccessTypeOffline, as well | ||
147 | // as ApprovalForce. | ||
148 | // It can also be used to pass the PKCE challenge. | ||
149 | // See https://www.oauth.com/oauth2-servers/pkce/ for more info. | ||
150 | func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { | ||
151 | var buf bytes.Buffer | ||
152 | buf.WriteString(c.Endpoint.AuthURL) | ||
153 | v := url.Values{ | ||
154 | "response_type": {"code"}, | ||
155 | "client_id": {c.ClientID}, | ||
156 | } | ||
157 | if c.RedirectURL != "" { | ||
158 | v.Set("redirect_uri", c.RedirectURL) | ||
159 | } | ||
160 | if len(c.Scopes) > 0 { | ||
161 | v.Set("scope", strings.Join(c.Scopes, " ")) | ||
162 | } | ||
163 | if state != "" { | ||
164 | // TODO(light): Docs say never to omit state; don't allow empty. | ||
165 | v.Set("state", state) | ||
166 | } | ||
167 | for _, opt := range opts { | ||
168 | opt.setValue(v) | ||
169 | } | ||
170 | if strings.Contains(c.Endpoint.AuthURL, "?") { | ||
171 | buf.WriteByte('&') | ||
172 | } else { | ||
173 | buf.WriteByte('?') | ||
174 | } | ||
175 | buf.WriteString(v.Encode()) | ||
176 | return buf.String() | ||
177 | } | ||
178 | |||
179 | // PasswordCredentialsToken converts a resource owner username and password | ||
180 | // pair into a token. | ||
181 | // | ||
182 | // Per the RFC, this grant type should only be used "when there is a high | ||
183 | // degree of trust between the resource owner and the client (e.g., the client | ||
184 | // is part of the device operating system or a highly privileged application), | ||
185 | // and when other authorization grant types are not available." | ||
186 | // See https://tools.ietf.org/html/rfc6749#section-4.3 for more info. | ||
187 | // | ||
188 | // The provided context optionally controls which HTTP client is used. See the HTTPClient variable. | ||
189 | func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { | ||
190 | v := url.Values{ | ||
191 | "grant_type": {"password"}, | ||
192 | "username": {username}, | ||
193 | "password": {password}, | ||
194 | } | ||
195 | if len(c.Scopes) > 0 { | ||
196 | v.Set("scope", strings.Join(c.Scopes, " ")) | ||
197 | } | ||
198 | return retrieveToken(ctx, c, v) | ||
199 | } | ||
200 | |||
201 | // Exchange converts an authorization code into a token. | ||
202 | // | ||
203 | // It is used after a resource provider redirects the user back | ||
204 | // to the Redirect URI (the URL obtained from AuthCodeURL). | ||
205 | // | ||
206 | // The provided context optionally controls which HTTP client is used. See the HTTPClient variable. | ||
207 | // | ||
208 | // The code will be in the *http.Request.FormValue("code"). Before | ||
209 | // calling Exchange, be sure to validate FormValue("state"). | ||
210 | // | ||
211 | // Opts may include the PKCE verifier code if previously used in AuthCodeURL. | ||
212 | // See https://www.oauth.com/oauth2-servers/pkce/ for more info. | ||
213 | func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) { | ||
214 | v := url.Values{ | ||
215 | "grant_type": {"authorization_code"}, | ||
216 | "code": {code}, | ||
217 | } | ||
218 | if c.RedirectURL != "" { | ||
219 | v.Set("redirect_uri", c.RedirectURL) | ||
220 | } | ||
221 | for _, opt := range opts { | ||
222 | opt.setValue(v) | ||
223 | } | ||
224 | return retrieveToken(ctx, c, v) | ||
225 | } | ||
226 | |||
227 | // Client returns an HTTP client using the provided token. | ||
228 | // The token will auto-refresh as necessary. The underlying | ||
229 | // HTTP transport will be obtained using the provided context. | ||
230 | // The returned client and its Transport should not be modified. | ||
231 | func (c *Config) Client(ctx context.Context, t *Token) *http.Client { | ||
232 | return NewClient(ctx, c.TokenSource(ctx, t)) | ||
233 | } | ||
234 | |||
235 | // TokenSource returns a TokenSource that returns t until t expires, | ||
236 | // automatically refreshing it as necessary using the provided context. | ||
237 | // | ||
238 | // Most users will use Config.Client instead. | ||
239 | func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource { | ||
240 | tkr := &tokenRefresher{ | ||
241 | ctx: ctx, | ||
242 | conf: c, | ||
243 | } | ||
244 | if t != nil { | ||
245 | tkr.refreshToken = t.RefreshToken | ||
246 | } | ||
247 | return &reuseTokenSource{ | ||
248 | t: t, | ||
249 | new: tkr, | ||
250 | } | ||
251 | } | ||
252 | |||
253 | // tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token" | ||
254 | // HTTP requests to renew a token using a RefreshToken. | ||
255 | type tokenRefresher struct { | ||
256 | ctx context.Context // used to get HTTP requests | ||
257 | conf *Config | ||
258 | refreshToken string | ||
259 | } | ||
260 | |||
261 | // WARNING: Token is not safe for concurrent access, as it | ||
262 | // updates the tokenRefresher's refreshToken field. | ||
263 | // Within this package, it is used by reuseTokenSource which | ||
264 | // synchronizes calls to this method with its own mutex. | ||
265 | func (tf *tokenRefresher) Token() (*Token, error) { | ||
266 | if tf.refreshToken == "" { | ||
267 | return nil, errors.New("oauth2: token expired and refresh token is not set") | ||
268 | } | ||
269 | |||
270 | tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{ | ||
271 | "grant_type": {"refresh_token"}, | ||
272 | "refresh_token": {tf.refreshToken}, | ||
273 | }) | ||
274 | |||
275 | if err != nil { | ||
276 | return nil, err | ||
277 | } | ||
278 | if tf.refreshToken != tk.RefreshToken { | ||
279 | tf.refreshToken = tk.RefreshToken | ||
280 | } | ||
281 | return tk, err | ||
282 | } | ||
283 | |||
284 | // reuseTokenSource is a TokenSource that holds a single token in memory | ||
285 | // and validates its expiry before each call to retrieve it with | ||
286 | // Token. If it's expired, it will be auto-refreshed using the | ||
287 | // new TokenSource. | ||
288 | type reuseTokenSource struct { | ||
289 | new TokenSource // called when t is expired. | ||
290 | |||
291 | mu sync.Mutex // guards t | ||
292 | t *Token | ||
293 | } | ||
294 | |||
295 | // Token returns the current token if it's still valid, else will | ||
296 | // refresh the current token (using r.Context for HTTP client | ||
297 | // information) and return the new one. | ||
298 | func (s *reuseTokenSource) Token() (*Token, error) { | ||
299 | s.mu.Lock() | ||
300 | defer s.mu.Unlock() | ||
301 | if s.t.Valid() { | ||
302 | return s.t, nil | ||
303 | } | ||
304 | t, err := s.new.Token() | ||
305 | if err != nil { | ||
306 | return nil, err | ||
307 | } | ||
308 | s.t = t | ||
309 | return t, nil | ||
310 | } | ||
311 | |||
312 | // StaticTokenSource returns a TokenSource that always returns the same token. | ||
313 | // Because the provided token t is never refreshed, StaticTokenSource is only | ||
314 | // useful for tokens that never expire. | ||
315 | func StaticTokenSource(t *Token) TokenSource { | ||
316 | return staticTokenSource{t} | ||
317 | } | ||
318 | |||
319 | // staticTokenSource is a TokenSource that always returns the same Token. | ||
320 | type staticTokenSource struct { | ||
321 | t *Token | ||
322 | } | ||
323 | |||
324 | func (s staticTokenSource) Token() (*Token, error) { | ||
325 | return s.t, nil | ||
326 | } | ||
327 | |||
328 | // HTTPClient is the context key to use with golang.org/x/net/context's | ||
329 | // WithValue function to associate an *http.Client value with a context. | ||
330 | var HTTPClient internal.ContextKey | ||
331 | |||
332 | // NewClient creates an *http.Client from a Context and TokenSource. | ||
333 | // The returned client is not valid beyond the lifetime of the context. | ||
334 | // | ||
335 | // Note that if a custom *http.Client is provided via the Context it | ||
336 | // is used only for token acquisition and is not used to configure the | ||
337 | // *http.Client returned from NewClient. | ||
338 | // | ||
339 | // As a special case, if src is nil, a non-OAuth2 client is returned | ||
340 | // using the provided context. This exists to support related OAuth2 | ||
341 | // packages. | ||
342 | func NewClient(ctx context.Context, src TokenSource) *http.Client { | ||
343 | if src == nil { | ||
344 | return internal.ContextClient(ctx) | ||
345 | } | ||
346 | return &http.Client{ | ||
347 | Transport: &Transport{ | ||
348 | Base: internal.ContextClient(ctx).Transport, | ||
349 | Source: ReuseTokenSource(nil, src), | ||
350 | }, | ||
351 | } | ||
352 | } | ||
353 | |||
354 | // ReuseTokenSource returns a TokenSource which repeatedly returns the | ||
355 | // same token as long as it's valid, starting with t. | ||
356 | // When its cached token is invalid, a new token is obtained from src. | ||
357 | // | ||
358 | // ReuseTokenSource is typically used to reuse tokens from a cache | ||
359 | // (such as a file on disk) between runs of a program, rather than | ||
360 | // obtaining new tokens unnecessarily. | ||
361 | // | ||
362 | // The initial token t may be nil, in which case the TokenSource is | ||
363 | // wrapped in a caching version if it isn't one already. This also | ||
364 | // means it's always safe to wrap ReuseTokenSource around any other | ||
365 | // TokenSource without adverse effects. | ||
366 | func ReuseTokenSource(t *Token, src TokenSource) TokenSource { | ||
367 | // Don't wrap a reuseTokenSource in itself. That would work, | ||
368 | // but cause an unnecessary number of mutex operations. | ||
369 | // Just build the equivalent one. | ||
370 | if rt, ok := src.(*reuseTokenSource); ok { | ||
371 | if t == nil { | ||
372 | // Just use it directly. | ||
373 | return rt | ||
374 | } | ||
375 | src = rt.new | ||
376 | } | ||
377 | return &reuseTokenSource{ | ||
378 | t: t, | ||
379 | new: src, | ||
380 | } | ||
381 | } | ||