Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py: 17%

53 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:22 +0000

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 elif not self.request_validator.authenticate_client_id(request.client_id, request): 

105 log.debug('Client authentication failed, %r.', request) 

106 raise errors.InvalidClientError(request=request) 

107 

108 # Ensure client is authorized use of this grant type 

109 self.validate_grant_type(request) 

110 

111 # REQUIRED. The refresh token issued to the client. 

112 log.debug('Validating refresh token %s for client %r.', 

113 request.refresh_token, request.client) 

114 if not self.request_validator.validate_refresh_token( 

115 request.refresh_token, request.client, request): 

116 log.debug('Invalid refresh token, %s, for client %r.', 

117 request.refresh_token, request.client) 

118 raise errors.InvalidGrantError(request=request) 

119 

120 original_scopes = utils.scope_to_list( 

121 self.request_validator.get_original_scopes( 

122 request.refresh_token, request)) 

123 

124 if request.scope: 

125 request.scopes = utils.scope_to_list(request.scope) 

126 if (not all(s in original_scopes for s in request.scopes) 

127 and not self.request_validator.is_within_original_scope( 

128 request.scopes, request.refresh_token, request)): 

129 log.debug('Refresh token %s lack requested scopes, %r.', 

130 request.refresh_token, request.scopes) 

131 raise errors.InvalidScopeError(request=request) 

132 else: 

133 request.scopes = original_scopes 

134 

135 for validator in self.custom_validators.post_token: 

136 validator(request)