1"""
2oauthlib.oauth2.rfc6749
3~~~~~~~~~~~~~~~~~~~~~~~
4
5This module is an implementation of various logic needed
6for consuming and providing OAuth 2.0 RFC6749.
7"""
8import logging
9
10from oauthlib.common import Request
11
12from .base import BaseEndpoint, catch_errors_and_unavailability
13
14log = logging.getLogger(__name__)
15
16
17class ResourceEndpoint(BaseEndpoint):
18
19 """Authorizes access to protected resources.
20
21 The client accesses protected resources by presenting the access
22 token to the resource server. The resource server MUST validate the
23 access token and ensure that it has not expired and that its scope
24 covers the requested resource. The methods used by the resource
25 server to validate the access token (as well as any error responses)
26 are beyond the scope of this specification but generally involve an
27 interaction or coordination between the resource server and the
28 authorization server::
29
30 # For most cases, returning a 403 should suffice.
31
32 The method in which the client utilizes the access token to
33 authenticate with the resource server depends on the type of access
34 token issued by the authorization server. Typically, it involves
35 using the HTTP "Authorization" request header field [RFC2617] with an
36 authentication scheme defined by the specification of the access
37 token type used, such as [RFC6750]::
38
39 # Access tokens may also be provided in query and body
40 https://example.com/protected?access_token=kjfch2345sdf # Query
41 access_token=sdf23409df # Body
42 """
43
44 def __init__(self, default_token, token_types):
45 BaseEndpoint.__init__(self)
46 self._tokens = token_types
47 self._default_token = default_token
48
49 @property
50 def default_token(self):
51 return self._default_token
52
53 @property
54 def default_token_type_handler(self):
55 return self.tokens.get(self.default_token)
56
57 @property
58 def tokens(self):
59 return self._tokens
60
61 @catch_errors_and_unavailability
62 def verify_request(self, uri, http_method='GET', body=None, headers=None,
63 scopes=None):
64 """Validate client, code etc, return body + headers"""
65 request = Request(uri, http_method, body, headers)
66 request.token_type = self.find_token_type(request)
67 request.scopes = scopes
68 token_type_handler = self.tokens.get(request.token_type,
69 self.default_token_type_handler)
70 log.debug('Dispatching token_type %s request to %r.',
71 request.token_type, token_type_handler)
72 return token_type_handler.validate_request(request), request
73
74 def find_token_type(self, request):
75 """Token type identification.
76
77 RFC 6749 does not provide a method for easily differentiating between
78 different token types during protected resource access. We estimate
79 the most likely token type (if any) by asking each known token type
80 to give an estimation based on the request.
81 """
82 estimates = sorted(((t.estimate_type(request), n)
83 for n, t in self.tokens.items()), reverse=True)
84 return estimates[0][1] if estimates else None