Skip to content

Commit 7ad7f4d

Browse files
authored
Refresh tokens before they expire (#486)
* Refresh tokens before they expire * Assign dict values to variables
1 parent 33c10f5 commit 7ad7f4d

File tree

1 file changed

+31
-20
lines changed

1 file changed

+31
-20
lines changed

twitchio/authentication/tokens.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -229,40 +229,51 @@ def request_paginated(
229229
)
230230
return iterator
231231

232+
async def _refresh_token(self, user_id: str, refresh: str) -> None:
233+
try:
234+
resp: RefreshTokenPayload = await self.__isolated.refresh_token(refresh)
235+
except HTTPException as e:
236+
if e.status >= 500:
237+
raise
238+
239+
self._tokens.pop(user_id, None)
240+
logger.warning('Token for "%s" was invalid and could not be refreshed.', user_id)
241+
else:
242+
logger.debug('Token for "%s" was successfully refreshed.', user_id)
243+
244+
self._tokens[user_id] = {
245+
"user_id": user_id,
246+
"token": resp.access_token,
247+
"refresh": resp.refresh_token,
248+
"last_validated": datetime.datetime.now().isoformat(),
249+
}
250+
232251
async def _revalidate_all(self) -> None:
233252
logger.debug("Attempting to revalidate all tokens that have passed the timeout on %s.", self.__class__.__qualname__)
234253

235254
for data in self._tokens.copy().values():
255+
user_id: str = data["user_id"]
256+
token: str = data["token"]
257+
refresh: str = data["refresh"]
236258
last_validated: datetime.datetime = datetime.datetime.fromisoformat(data["last_validated"])
259+
237260
if last_validated + datetime.timedelta(minutes=60) > datetime.datetime.now():
238261
continue
239262

240263
try:
241-
await self.__isolated.validate_token(data["token"])
264+
valid_resp: ValidateTokenPayload = await self.__isolated.validate_token(token)
242265
except HTTPException as e:
243266
if e.status >= 500:
244267
raise
245268

246-
logger.debug('Token for "%s" was invalid or expired. Attempting to refresh token.', data["user_id"])
247-
248-
try:
249-
refresh: RefreshTokenPayload = await self.__isolated.refresh_token(data["refresh"])
250-
except HTTPException as e:
251-
if e.status >= 500:
252-
raise
253-
254-
self._tokens.pop(data["user_id"], None)
255-
logger.warning('Token for "%s" was invalid and could not be refreshed.', data["user_id"])
256-
continue
257-
258-
logger.debug('Token for "%s" was successfully refreshed.', data["user_id"])
269+
logger.debug('Token for "%s" was invalid or expired. Attempting to refresh token.', user_id)
270+
await self._refresh_token(user_id, refresh)
271+
else:
272+
expires_in: int = valid_resp["expires_in"]
259273

260-
self._tokens[data["user_id"]] = {
261-
"user_id": data["user_id"],
262-
"token": refresh.access_token,
263-
"refresh": refresh.refresh_token,
264-
"last_validated": datetime.datetime.now().isoformat(),
265-
}
274+
if expires_in <= 60:
275+
logger.debug('Token for "%s" expires in %s seconds. Attempting to refresh token.', user_id, expires_in)
276+
await self._refresh_token(user_id, refresh)
266277

267278
async def __validate_loop(self) -> None:
268279
logger.debug("Started the token validation loop on %s.", self.__class__.__qualname__)

0 commit comments

Comments
 (0)