import oauthlib (a dependency of the project)
[yelp-api-cdsw] / oauthlib / oauth2 / rfc6749 / request_validator.py
1 # -*- coding: utf-8 -*-
2 """
3 oauthlib.oauth2.rfc6749.grant_types
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 """
6 from __future__ import unicode_literals, absolute_import
7
8 import logging
9
10 log = logging.getLogger(__name__)
11
12
13 class RequestValidator(object):
14
15     def client_authentication_required(self, request, *args, **kwargs):
16         """Determine if client authentication is required for current request.
17
18         According to the rfc6749, client authentication is required in the following cases:
19             - Resource Owner Password Credentials Grant, when Client type is Confidential or when
20               Client was issued client credentials or whenever Client provided client
21               authentication, see `Section 4.3.2`_.
22             - Authorization Code Grant, when Client type is Confidential or when Client was issued
23               client credentials or whenever Client provided client authentication,
24               see `Section 4.1.3`_.
25             - Refresh Token Grant, when Client type is Confidential or when Client was issued
26               client credentials or whenever Client provided client authentication, see
27               `Section 6`_
28
29         :param request: oauthlib.common.Request
30         :rtype: True or False
31
32         Method is used by:
33             - Authorization Code Grant
34             - Resource Owner Password Credentials Grant
35             - Refresh Token Grant
36
37         .. _`Section 4.3.2`: http://tools.ietf.org/html/rfc6749#section-4.3.2
38         .. _`Section 4.1.3`: http://tools.ietf.org/html/rfc6749#section-4.1.3
39         .. _`Section 6`: http://tools.ietf.org/html/rfc6749#section-6
40         """
41         return True
42
43     def authenticate_client(self, request, *args, **kwargs):
44         """Authenticate client through means outside the OAuth 2 spec.
45
46         Means of authentication is negotiated beforehand and may for example
47         be `HTTP Basic Authentication Scheme`_ which utilizes the Authorization
48         header.
49
50         Headers may be accesses through request.headers and parameters found in
51         both body and query can be obtained by direct attribute access, i.e.
52         request.client_id for client_id in the URL query.
53
54         OBS! Certain grant types rely on this authentication, possibly with
55         other fallbacks, and for them to recognize this authorization please
56         set the client attribute on the request (request.client). Note that
57         preferably this client object should have a client_id attribute of
58         unicode type (request.client.client_id).
59
60         :param request: oauthlib.common.Request
61         :rtype: True or False
62
63         Method is used by:
64             - Authorization Code Grant
65             - Resource Owner Password Credentials Grant (may be disabled)
66             - Client Credentials Grant
67             - Refresh Token Grant
68
69         .. _`HTTP Basic Authentication Scheme`: http://tools.ietf.org/html/rfc1945#section-11.1
70         """
71         raise NotImplementedError('Subclasses must implement this method.')
72
73     def authenticate_client_id(self, client_id, request, *args, **kwargs):
74         """Ensure client_id belong to a non-confidential client.
75
76         A non-confidential client is one that is not required to authenticate
77         through other means, such as using HTTP Basic.
78
79         Note, while not strictly necessary it can often be very convenient
80         to set request.client to the client object associated with the
81         given client_id.
82
83         :param request: oauthlib.common.Request
84         :rtype: True or False
85
86         Method is used by:
87             - Authorization Code Grant
88         """
89         raise NotImplementedError('Subclasses must implement this method.')
90
91     def confirm_redirect_uri(self, client_id, code, redirect_uri, client,
92                              *args, **kwargs):
93         """Ensure client is authorized to redirect to the redirect_uri requested.
94
95         If the client specifies a redirect_uri when obtaining code then
96         that redirect URI must be bound to the code and verified equal
97         in this method.
98
99         All clients should register the absolute URIs of all URIs they intend
100         to redirect to. The registration is outside of the scope of oauthlib.
101
102         :param client_id: Unicode client identifier
103         :param code: Unicode authorization_code.
104         :param redirect_uri: Unicode absolute URI
105         :param client: Client object set by you, see authenticate_client.
106         :param request: The HTTP Request (oauthlib.common.Request)
107         :rtype: True or False
108
109         Method is used by:
110             - Authorization Code Grant (during token request)
111         """
112         raise NotImplementedError('Subclasses must implement this method.')
113
114     def get_default_redirect_uri(self, client_id, request, *args, **kwargs):
115         """Get the default redirect URI for the client.
116
117         :param client_id: Unicode client identifier
118         :param request: The HTTP Request (oauthlib.common.Request)
119         :rtype: The default redirect URI for the client
120
121         Method is used by:
122             - Authorization Code Grant
123             - Implicit Grant
124         """
125         raise NotImplementedError('Subclasses must implement this method.')
126
127     def get_default_scopes(self, client_id, request, *args, **kwargs):
128         """Get the default scopes for the client.
129
130         :param client_id: Unicode client identifier
131         :param request: The HTTP Request (oauthlib.common.Request)
132         :rtype: List of default scopes
133
134         Method is used by all core grant types:
135             - Authorization Code Grant
136             - Implicit Grant
137             - Resource Owner Password Credentials Grant
138             - Client Credentials grant
139         """
140         raise NotImplementedError('Subclasses must implement this method.')
141
142     def get_original_scopes(self, refresh_token, request, *args, **kwargs):
143         """Get the list of scopes associated with the refresh token.
144
145         :param refresh_token: Unicode refresh token
146         :param request: The HTTP Request (oauthlib.common.Request)
147         :rtype: List of scopes.
148
149         Method is used by:
150             - Refresh token grant
151         """
152         raise NotImplementedError('Subclasses must implement this method.')
153
154     def is_within_original_scope(self, request_scopes, refresh_token, request, *args, **kwargs):
155         """Check if requested scopes are within a scope of the refresh token.
156
157         When access tokens are refreshed the scope of the new token
158         needs to be within the scope of the original token. This is
159         ensured by checking that all requested scopes strings are on
160         the list returned by the get_original_scopes. If this check
161         fails, is_within_original_scope is called. The method can be
162         used in situations where returning all valid scopes from the
163         get_original_scopes is not practical.
164
165         :param request_scopes: A list of scopes that were requested by client
166         :param refresh_token: Unicode refresh_token
167         :param request: The HTTP Request (oauthlib.common.Request)
168         :rtype: True or False
169
170         Method is used by:
171             - Refresh token grant
172         """
173         return False
174
175     def invalidate_authorization_code(self, client_id, code, request, *args, **kwargs):
176         """Invalidate an authorization code after use.
177
178         :param client_id: Unicode client identifier
179         :param code: The authorization code grant (request.code).
180         :param request: The HTTP Request (oauthlib.common.Request)
181
182         Method is used by:
183             - Authorization Code Grant
184         """
185         raise NotImplementedError('Subclasses must implement this method.')
186
187     def revoke_token(self, token, token_type_hint, request, *args, **kwargs):
188         """Revoke an access or refresh token.
189
190         :param token: The token string.
191         :param token_type_hint: access_token or refresh_token.
192         :param request: The HTTP Request (oauthlib.common.Request)
193
194         Method is used by:
195             - Revocation Endpoint
196         """
197         raise NotImplementedError('Subclasses must implement this method.')
198
199     def rotate_refresh_token(self, request):
200         """Determine whether to rotate the refresh token. Default, yes.
201
202         When access tokens are refreshed the old refresh token can be kept
203         or replaced with a new one (rotated). Return True to rotate and
204         and False for keeping original.
205
206         :param request: oauthlib.common.Request
207         :rtype: True or False
208
209         Method is used by:
210             - Refresh Token Grant
211         """
212         return True
213
214     def save_authorization_code(self, client_id, code, request, *args, **kwargs):
215         """Persist the authorization_code.
216
217         The code should at minimum be associated with:
218             - a client and it's client_id
219             - the redirect URI used (request.redirect_uri)
220             - whether the redirect URI used is the client default or not
221             - a resource owner / user (request.user)
222             - authorized scopes (request.scopes)
223
224         The authorization code grant dict (code) holds at least the key 'code'::
225
226             {'code': 'sdf345jsdf0934f'}
227
228         :param client_id: Unicode client identifier
229         :param code: A dict of the authorization code grant.
230         :param request: The HTTP Request (oauthlib.common.Request)
231         :rtype: The default redirect URI for the client
232
233         Method is used by:
234             - Authorization Code Grant
235         """
236         raise NotImplementedError('Subclasses must implement this method.')
237
238     def save_bearer_token(self, token, request, *args, **kwargs):
239         """Persist the Bearer token.
240
241         The Bearer token should at minimum be associated with:
242             - a client and it's client_id, if available
243             - a resource owner / user (request.user)
244             - authorized scopes (request.scopes)
245             - an expiration time
246             - a refresh token, if issued
247
248         The Bearer token dict may hold a number of items::
249
250             {
251                 'token_type': 'Bearer',
252                 'access_token': 'askfjh234as9sd8',
253                 'expires_in': 3600,
254                 'scope': 'string of space separated authorized scopes',
255                 'refresh_token': '23sdf876234',  # if issued
256                 'state': 'given_by_client',  # if supplied by client
257             }
258
259         Note that while "scope" is a string-separated list of authorized scopes,
260         the original list is still available in request.scopes
261
262         :param client_id: Unicode client identifier
263         :param token: A Bearer token dict
264         :param request: The HTTP Request (oauthlib.common.Request)
265         :rtype: The default redirect URI for the client
266
267         Method is used by all core grant types issuing Bearer tokens:
268             - Authorization Code Grant
269             - Implicit Grant
270             - Resource Owner Password Credentials Grant (might not associate a client)
271             - Client Credentials grant
272         """
273         raise NotImplementedError('Subclasses must implement this method.')
274
275     def validate_bearer_token(self, token, scopes, request):
276         """Ensure the Bearer token is valid and authorized access to scopes.
277
278         :param token: A string of random characters.
279         :param scopes: A list of scopes associated with the protected resource.
280         :param request: The HTTP Request (oauthlib.common.Request)
281
282         A key to OAuth 2 security and restricting impact of leaked tokens is
283         the short expiration time of tokens, *always ensure the token has not
284         expired!*.
285
286         Two different approaches to scope validation:
287
288             1) all(scopes). The token must be authorized access to all scopes
289                             associated with the resource. For example, the
290                             token has access to ``read-only`` and ``images``,
291                             thus the client can view images but not upload new.
292                             Allows for fine grained access control through
293                             combining various scopes.
294
295             2) any(scopes). The token must be authorized access to one of the
296                             scopes associated with the resource. For example,
297                             token has access to ``read-only-images``.
298                             Allows for fine grained, although arguably less
299                             convenient, access control.
300
301         A powerful way to use scopes would mimic UNIX ACLs and see a scope
302         as a group with certain privileges. For a restful API these might
303         map to HTTP verbs instead of read, write and execute.
304
305         Note, the request.user attribute can be set to the resource owner
306         associated with this token. Similarly the request.client and
307         request.scopes attribute can be set to associated client object
308         and authorized scopes. If you then use a decorator such as the
309         one provided for django these attributes will be made available
310         in all protected views as keyword arguments.
311
312         :param token: Unicode Bearer token
313         :param scopes: List of scopes (defined by you)
314         :param request: The HTTP Request (oauthlib.common.Request)
315         :rtype: True or False
316
317         Method is indirectly used by all core Bearer token issuing grant types:
318             - Authorization Code Grant
319             - Implicit Grant
320             - Resource Owner Password Credentials Grant
321             - Client Credentials Grant
322         """
323         raise NotImplementedError('Subclasses must implement this method.')
324
325     def validate_client_id(self, client_id, request, *args, **kwargs):
326         """Ensure client_id belong to a valid and active client.
327
328         Note, while not strictly necessary it can often be very convenient
329         to set request.client to the client object associated with the
330         given client_id.
331
332         :param request: oauthlib.common.Request
333         :rtype: True or False
334
335         Method is used by:
336             - Authorization Code Grant
337             - Implicit Grant
338         """
339         raise NotImplementedError('Subclasses must implement this method.')
340
341     def validate_code(self, client_id, code, client, request, *args, **kwargs):
342         """Ensure the authorization_code is valid and assigned to client.
343
344         OBS! The request.user attribute should be set to the resource owner
345         associated with this authorization code. Similarly request.scopes and
346         request.state must also be set.
347
348         :param client_id: Unicode client identifier
349         :param code: Unicode authorization code
350         :param client: Client object set by you, see authenticate_client.
351         :param request: The HTTP Request (oauthlib.common.Request)
352         :rtype: True or False
353
354         Method is used by:
355             - Authorization Code Grant
356         """
357         raise NotImplementedError('Subclasses must implement this method.')
358
359     def validate_grant_type(self, client_id, grant_type, client, request, *args, **kwargs):
360         """Ensure client is authorized to use the grant_type requested.
361
362         :param client_id: Unicode client identifier
363         :param grant_type: Unicode grant type, i.e. authorization_code, password.
364         :param client: Client object set by you, see authenticate_client.
365         :param request: The HTTP Request (oauthlib.common.Request)
366         :rtype: True or False
367
368         Method is used by:
369             - Authorization Code Grant
370             - Resource Owner Password Credentials Grant
371             - Client Credentials Grant
372             - Refresh Token Grant
373         """
374         raise NotImplementedError('Subclasses must implement this method.')
375
376     def validate_redirect_uri(self, client_id, redirect_uri, request, *args, **kwargs):
377         """Ensure client is authorized to redirect to the redirect_uri requested.
378
379         All clients should register the absolute URIs of all URIs they intend
380         to redirect to. The registration is outside of the scope of oauthlib.
381
382         :param client_id: Unicode client identifier
383         :param redirect_uri: Unicode absolute URI
384         :param request: The HTTP Request (oauthlib.common.Request)
385         :rtype: True or False
386
387         Method is used by:
388             - Authorization Code Grant
389             - Implicit Grant
390         """
391         raise NotImplementedError('Subclasses must implement this method.')
392
393     def validate_refresh_token(self, refresh_token, client, request, *args, **kwargs):
394         """Ensure the Bearer token is valid and authorized access to scopes.
395
396         OBS! The request.user attribute should be set to the resource owner
397         associated with this refresh token.
398
399         :param refresh_token: Unicode refresh token
400         :param client: Client object set by you, see authenticate_client.
401         :param request: The HTTP Request (oauthlib.common.Request)
402         :rtype: True or False
403
404         Method is used by:
405             - Authorization Code Grant (indirectly by issuing refresh tokens)
406             - Resource Owner Password Credentials Grant (also indirectly)
407             - Refresh Token Grant
408         """
409         raise NotImplementedError('Subclasses must implement this method.')
410
411     def validate_response_type(self, client_id, response_type, client, request, *args, **kwargs):
412         """Ensure client is authorized to use the response_type requested.
413
414         :param client_id: Unicode client identifier
415         :param response_type: Unicode response type, i.e. code, token.
416         :param client: Client object set by you, see authenticate_client.
417         :param request: The HTTP Request (oauthlib.common.Request)
418         :rtype: True or False
419
420         Method is used by:
421             - Authorization Code Grant
422             - Implicit Grant
423         """
424         raise NotImplementedError('Subclasses must implement this method.')
425
426     def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs):
427         """Ensure the client is authorized access to requested scopes.
428
429         :param client_id: Unicode client identifier
430         :param scopes: List of scopes (defined by you)
431         :param client: Client object set by you, see authenticate_client.
432         :param request: The HTTP Request (oauthlib.common.Request)
433         :rtype: True or False
434
435         Method is used by all core grant types:
436             - Authorization Code Grant
437             - Implicit Grant
438             - Resource Owner Password Credentials Grant
439             - Client Credentials Grant
440         """
441         raise NotImplementedError('Subclasses must implement this method.')
442
443     def validate_user(self, username, password, client, request, *args, **kwargs):
444         """Ensure the username and password is valid.
445
446         OBS! The validation should also set the user attribute of the request
447         to a valid resource owner, i.e. request.user = username or similar. If
448         not set you will be unable to associate a token with a user in the
449         persistance method used (commonly, save_bearer_token).
450
451         :param username: Unicode username
452         :param password: Unicode password
453         :param client: Client object set by you, see authenticate_client.
454         :param request: The HTTP Request (oauthlib.common.Request)
455         :rtype: True or False
456
457         Method is used by:
458             - Resource Owner Password Credentials Grant
459         """
460         raise NotImplementedError('Subclasses must implement this method.')

Benjamin Mako Hill || Want to submit a patch?