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 
    11from oauthlib.oauth2.rfc6749 import utils 
    12 
    13from .base import BaseEndpoint, catch_errors_and_unavailability 
    14 
    15log = logging.getLogger(__name__) 
    16 
    17 
    18class TokenEndpoint(BaseEndpoint): 
    19 
    20    """Token issuing endpoint. 
    21 
    22    The token endpoint is used by the client to obtain an access token by 
    23    presenting its authorization grant or refresh token.  The token 
    24    endpoint is used with every authorization grant except for the 
    25    implicit grant type (since an access token is issued directly). 
    26 
    27    The means through which the client obtains the location of the token 
    28    endpoint are beyond the scope of this specification, but the location 
    29    is typically provided in the service documentation. 
    30 
    31    The endpoint URI MAY include an "application/x-www-form-urlencoded" 
    32    formatted (per `Appendix B`_) query component, 
    33    which MUST be retained when adding additional query parameters.  The 
    34    endpoint URI MUST NOT include a fragment component:: 
    35 
    36        https://example.com/path?query=component             # OK 
    37        https://example.com/path?query=component#fragment    # Not OK 
    38 
    39    Since requests to the token endpoint result in the transmission of 
    40    clear-text credentials (in the HTTP request and response), the 
    41    authorization server MUST require the use of TLS as described in 
    42    Section 1.6 when sending requests to the token endpoint:: 
    43 
    44        # We will deny any request which URI schema is not with https 
    45 
    46    The client MUST use the HTTP "POST" method when making access token 
    47    requests:: 
    48 
    49        # HTTP method is currently not enforced 
    50 
    51    Parameters sent without a value MUST be treated as if they were 
    52    omitted from the request.  The authorization server MUST ignore 
    53    unrecognized request parameters.  Request and response parameters 
    54    MUST NOT be included more than once:: 
    55 
    56        # Delegated to each grant type. 
    57 
    58    .. _`Appendix B`: https://tools.ietf.org/html/rfc6749#appendix-B 
    59    """ 
    60 
    61    valid_request_methods = ('POST',) 
    62 
    63    def __init__(self, default_grant_type, default_token_type, grant_types): 
    64        BaseEndpoint.__init__(self) 
    65        self._grant_types = grant_types 
    66        self._default_token_type = default_token_type 
    67        self._default_grant_type = default_grant_type 
    68 
    69    @property 
    70    def grant_types(self): 
    71        return self._grant_types 
    72 
    73    @property 
    74    def default_grant_type(self): 
    75        return self._default_grant_type 
    76 
    77    @property 
    78    def default_grant_type_handler(self): 
    79        return self.grant_types.get(self.default_grant_type) 
    80 
    81    @property 
    82    def default_token_type(self): 
    83        return self._default_token_type 
    84 
    85    @catch_errors_and_unavailability 
    86    def create_token_response(self, uri, http_method='POST', body=None, 
    87                              headers=None, credentials=None, grant_type_for_scope=None, 
    88                              claims=None): 
    89        """Extract grant_type and route to the designated handler.""" 
    90        request = Request( 
    91            uri, http_method=http_method, body=body, headers=headers) 
    92        self.validate_token_request(request) 
    93        # 'scope' is an allowed Token Request param in both the "Resource Owner Password Credentials Grant" 
    94        # and "Client Credentials Grant" flows 
    95        # https://tools.ietf.org/html/rfc6749#section-4.3.2 
    96        # https://tools.ietf.org/html/rfc6749#section-4.4.2 
    97        request.scopes = utils.scope_to_list(request.scope) 
    98 
    99        request.extra_credentials = credentials 
    100        if grant_type_for_scope: 
    101            request.grant_type = grant_type_for_scope 
    102 
    103        # OpenID Connect claims, if provided.  The server using oauthlib might choose 
    104        # to implement the claims parameter of the Authorization Request.  In this case 
    105        # it should retrieve those claims and pass them via the claims argument here, 
    106        # as a dict. 
    107        if claims: 
    108            request.claims = claims 
    109 
    110        grant_type_handler = self.grant_types.get(request.grant_type, 
    111                                                  self.default_grant_type_handler) 
    112        log.debug('Dispatching grant_type %s request to %r.', 
    113                  request.grant_type, grant_type_handler) 
    114        return grant_type_handler.create_token_response( 
    115            request, self.default_token_type) 
    116 
    117    def validate_token_request(self, request): 
    118        self._raise_on_bad_method(request) 
    119        self._raise_on_bad_post_request(request)