1""" 
    2oauthlib.oauth2.rfc6749.grant_types 
    3~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4""" 
    5import json 
    6import logging 
    7 
    8from .. import errors, utils 
    9from .base import GrantTypeBase 
    10 
    11log = logging.getLogger(__name__) 
    12 
    13 
    14class RefreshTokenGrant(GrantTypeBase): 
    15 
    16    """`Refresh token grant`_ 
    17 
    18    .. _`Refresh token grant`: https://tools.ietf.org/html/rfc6749#section-6 
    19    """ 
    20 
    21    def __init__(self, request_validator=None, 
    22                 issue_new_refresh_tokens=True, 
    23                 **kwargs): 
    24        super().__init__( 
    25            request_validator, 
    26            issue_new_refresh_tokens=issue_new_refresh_tokens, 
    27            **kwargs) 
    28 
    29    def create_token_response(self, request, token_handler): 
    30        """Create a new access token from a refresh_token. 
    31 
    32        :param request: OAuthlib request. 
    33        :type request: oauthlib.common.Request 
    34        :param token_handler: A token handler instance, for example of type 
    35                              oauthlib.oauth2.BearerToken. 
    36 
    37        If valid and authorized, the authorization server issues an access 
    38        token as described in `Section 5.1`_. If the request failed 
    39        verification or is invalid, the authorization server returns an error 
    40        response as described in `Section 5.2`_. 
    41 
    42        The authorization server MAY issue a new refresh token, in which case 
    43        the client MUST discard the old refresh token and replace it with the 
    44        new refresh token. The authorization server MAY revoke the old 
    45        refresh token after issuing a new refresh token to the client. If a 
    46        new refresh token is issued, the refresh token scope MUST be 
    47        identical to that of the refresh token included by the client in the 
    48        request. 
    49 
    50        .. _`Section 5.1`: https://tools.ietf.org/html/rfc6749#section-5.1 
    51        .. _`Section 5.2`: https://tools.ietf.org/html/rfc6749#section-5.2 
    52        """ 
    53        headers = self._get_default_headers() 
    54        try: 
    55            log.debug('Validating refresh token request, %r.', request) 
    56            self.validate_token_request(request) 
    57        except errors.OAuth2Error as e: 
    58            log.debug('Client error in token request, %s.', e) 
    59            headers.update(e.headers) 
    60            return headers, e.json, e.status_code 
    61 
    62        token = token_handler.create_token(request, 
    63                                           refresh_token=self.issue_new_refresh_tokens) 
    64 
    65        for modifier in self._token_modifiers: 
    66            token = modifier(token, token_handler, request) 
    67 
    68        self.request_validator.save_token(token, request) 
    69 
    70        log.debug('Issuing new token to client id %r (%r), %r.', 
    71                  request.client_id, request.client, token) 
    72        headers.update(self._create_cors_headers(request)) 
    73        return headers, json.dumps(token), 200 
    74 
    75    def validate_token_request(self, request): 
    76        """ 
    77        :param request: OAuthlib request. 
    78        :type request: oauthlib.common.Request 
    79        """ 
    80        # REQUIRED. Value MUST be set to "refresh_token". 
    81        if request.grant_type != 'refresh_token': 
    82            raise errors.UnsupportedGrantTypeError(request=request) 
    83 
    84        for validator in self.custom_validators.pre_token: 
    85            validator(request) 
    86 
    87        if request.refresh_token is None: 
    88            raise errors.InvalidRequestError( 
    89                description='Missing refresh token parameter.', 
    90                request=request) 
    91 
    92        # Because refresh tokens are typically long-lasting credentials used to 
    93        # request additional access tokens, the refresh token is bound to the 
    94        # client to which it was issued.  If the client type is confidential or 
    95        # the client was issued client credentials (or assigned other 
    96        # authentication requirements), the client MUST authenticate with the 
    97        # authorization server as described in Section 3.2.1. 
    98        # https://tools.ietf.org/html/rfc6749#section-3.2.1 
    99        if self.request_validator.client_authentication_required(request): 
    100            log.debug('Authenticating client, %r.', request) 
    101            if not self.request_validator.authenticate_client(request): 
    102                log.debug('Invalid client (%r), denying access.', request) 
    103                raise errors.InvalidClientError(request=request) 
    104            # Ensure that request.client_id is set. 
    105            if request.client_id is None and request.client is not None: 
    106                request.client_id = request.client.client_id 
    107        elif not self.request_validator.authenticate_client_id(request.client_id, request): 
    108            log.debug('Client authentication failed, %r.', request) 
    109            raise errors.InvalidClientError(request=request) 
    110 
    111        # Ensure client is authorized use of this grant type 
    112        self.validate_grant_type(request) 
    113 
    114        # REQUIRED. The refresh token issued to the client. 
    115        log.debug('Validating refresh token %s for client %r.', 
    116                  request.refresh_token, request.client) 
    117        if not self.request_validator.validate_refresh_token( 
    118                request.refresh_token, request.client, request): 
    119            log.debug('Invalid refresh token, %s, for client %r.', 
    120                      request.refresh_token, request.client) 
    121            raise errors.InvalidGrantError(request=request) 
    122 
    123        original_scopes = utils.scope_to_list( 
    124            self.request_validator.get_original_scopes( 
    125                request.refresh_token, request)) 
    126 
    127        if request.scope: 
    128            request.scopes = utils.scope_to_list(request.scope) 
    129            if (not all(s in original_scopes for s in request.scopes) 
    130                and not self.request_validator.is_within_original_scope( 
    131                    request.scopes, request.refresh_token, request)): 
    132                log.debug('Refresh token %s lack requested scopes, %r.', 
    133                          request.refresh_token, request.scopes) 
    134                raise errors.InvalidScopeError(request=request) 
    135        else: 
    136            request.scopes = original_scopes 
    137 
    138        for validator in self.custom_validators.post_token: 
    139            validator(request)