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

Benjamin Mako Hill || Want to submit a patch?