@@ -28,6 +28,7 @@ def __init__(
2828 access_token = None ,
2929 refresh_token = None ,
3030 network_layer = None ,
31+ refresh_lock = None ,
3132 ):
3233 """
3334 :param client_id:
@@ -62,14 +63,18 @@ def __init__(
6263 If specified, use it to make network requests. If not, the default network implementation will be used.
6364 :type network_layer:
6465 :class:`Network`
66+ :param refresh_lock:
67+ Lock used to synchronize token refresh. If not specified, then a :class:`threading.Lock` will be used.
68+ :type refresh_lock:
69+ Context Manager
6570 """
6671 self ._client_id = client_id
6772 self ._client_secret = client_secret
68- self ._store_tokens = store_tokens
73+ self ._store_tokens_callback = store_tokens
6974 self ._access_token = access_token
7075 self ._refresh_token = refresh_token
7176 self ._network_layer = network_layer if network_layer else DefaultNetwork ()
72- self ._refresh_lock = Lock ()
77+ self ._refresh_lock = refresh_lock or Lock ()
7378 self ._box_device_id = box_device_id
7479 self ._box_device_name = box_device_name
7580
@@ -158,6 +163,17 @@ def _refresh(self, access_token):
158163
159164 return self .send_token_request (data , access_token )
160165
166+ def _get_tokens (self ):
167+ """
168+ Get the current access and refresh tokens.
169+
170+ :return:
171+ Tuple containing the current access token and refresh token.
172+ :rtype:
173+ `tuple` of (`unicode`, `unicode`)
174+ """
175+ return self ._access_token , self ._refresh_token
176+
161177 def refresh (self , access_token_to_refresh ):
162178 """
163179 Refresh the access token and the refresh token and return the access_token, refresh_token tuple. The access
@@ -169,16 +185,17 @@ def refresh(self, access_token_to_refresh):
169185 `unicode`
170186 """
171187 with self ._refresh_lock :
188+ access_token , refresh_token = self ._get_tokens ()
172189 # The lock here is for handling that case that multiple requests fail, due to access token expired, at the
173190 # same time to avoid multiple session renewals.
174- if access_token_to_refresh == self . _access_token :
191+ if access_token_to_refresh == access_token :
175192 # If the active access token is the same as the token needs to be refreshed, we make the request to
176193 # refresh the token.
177194 return self ._refresh (access_token_to_refresh )
178195 else :
179196 # If the active access token (self._access_token) is not the same as the token needs to be refreshed,
180197 # it means the expired token has already been refreshed. Simply return the current active tokens.
181- return self . _access_token , self . _refresh_token
198+ return access_token , refresh_token
182199
183200 @staticmethod
184201 def _get_state_csrf_token ():
@@ -195,6 +212,10 @@ def _get_state_csrf_token():
195212 ascii_len = len (ascii_alphabet )
196213 return 'box_csrf_token_' + '' .join (ascii_alphabet [int (system_random .random () * ascii_len )] for _ in range (16 ))
197214
215+ def _store_tokens (self , access_token , refresh_token ):
216+ if self ._store_tokens_callback is not None :
217+ self ._store_tokens_callback (access_token , refresh_token )
218+
198219 def send_token_request (self , data , access_token , expect_refresh_token = True ):
199220 """
200221 Send the request to acquire or refresh an access token.
@@ -231,6 +252,5 @@ def send_token_request(self, data, access_token, expect_refresh_token=True):
231252 raise BoxOAuthException (network_response .status_code , network_response .content , url , 'POST' )
232253 except (ValueError , KeyError ):
233254 raise BoxOAuthException (network_response .status_code , network_response .content , url , 'POST' )
234- if self ._store_tokens :
235- self ._store_tokens (self ._access_token , self ._refresh_token )
255+ self ._store_tokens (self ._access_token , self ._refresh_token )
236256 return self ._access_token , self ._refresh_token
0 commit comments