refresher.py (3272B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\clientRefreshToken\refresher.py 2 from __future__ import absolute_import 3 import uthread2 4 import requests 5 import datetime 6 import logging 7 from .discovery_hacks import discover_refresh_parameters_from_user_token 8 logger = logging.getLogger(__name__) 9 10 class Refresher(object): 11 12 def __init__(self, initial_user_token_payload, initial_refresh_token): 13 client_id, token_endpoint = discover_refresh_parameters_from_user_token(initial_user_token_payload) 14 self.client_id = client_id 15 self.refresh_token = initial_refresh_token 16 self.token_endpoint = token_endpoint 17 self.access_token = None 18 self.expires = None 19 self.callbacks = [] 20 uthread2.StartTasklet(self._maintain_fresh_token) 21 22 def _maintain_fresh_token(self): 23 while True: 24 try: 25 self._refresh() 26 self.broadcast(self.access_token) 27 uthread2.sleep(max(0, self.expires - 90)) 28 except requests.HTTPError as http_error: 29 response = http_error.response 30 if response is not None and 400 <= response.status_code < 500: 31 reportHTTPError(http_error, message='token refresh rejected, stopping refresher') 32 return 33 reportHTTPError(http_error, message='token refresh request failed') 34 uthread2.sleep(1) 35 except (requests.ConnectionError, requests.Timeout) as e: 36 logger.warning('token refresh transient network error: %s', e) 37 uthread2.sleep(1) 38 except Exception: 39 logger.exception('refreshing access token failed') 40 uthread2.sleep(1) 41 42 def add_callback(self, callback): 43 if not callable(callback): 44 logger.warning('callback not callable: %s', callback) 45 return 46 self.callbacks.append(callback) 47 callback(self.access_token) 48 49 def broadcast(self, *args): 50 for callback in self.callbacks: 51 callback(*args) 52 53 def _refresh(self): 54 body = {'grant_type': 'refresh_token', 55 'client_id': self.client_id, 56 'refresh_token': self.refresh_token} 57 response = requests.post(self.token_endpoint, data=body, timeout=(5, 15)) 58 response.raise_for_status() 59 content = response.json() 60 access_token = content['access_token'] 61 if not access_token: 62 raise RuntimeError('access token empty on refresh') 63 refresh_token = content['refresh_token'] 64 if not refresh_token: 65 raise RuntimeError('refresh token empty on refresh') 66 self.access_token = access_token 67 self.refresh_token = refresh_token 68 self.expires = content['expires_in'] 69 logger.debug('token refreshed, expires in %s', datetime.timedelta(seconds=self.expires)) 70 71 72 def reportHTTPError(http_error, message = ''): 73 extra = dict() 74 try: 75 resp_data = http_error.response.json() 76 extra.update(resp_data) 77 except ValueError: 78 extra['response_content'] = str(http_error.response.content) 79 80 if not message: 81 message = str(http_error) 82 logger.exception(message, extra=extra)