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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

56 statements  

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)