Refresh token workaround because expires to fast

This commit is contained in:
Andre Basche 2023-04-14 23:15:07 +02:00
parent e82c14ec99
commit 272556586e
2 changed files with 25 additions and 2 deletions

View file

@ -3,6 +3,7 @@ import logging
import re import re
import secrets import secrets
import urllib import urllib
from datetime import datetime, timedelta
from pprint import pformat from pprint import pformat
from typing import List, Tuple from typing import List, Tuple
from urllib import parse from urllib import parse
@ -16,6 +17,9 @@ _LOGGER = logging.getLogger(__name__)
class HonAuth: class HonAuth:
_TOKEN_EXPIRES_AFTER_HOURS = 8
_TOKEN_EXPIRE_WARNING_HOURS = 7
def __init__(self, session, email, password, device) -> None: def __init__(self, session, email, password, device) -> None:
self._session = session self._session = session
self._email = email self._email = email
@ -26,6 +30,7 @@ class HonAuth:
self._id_token = "" self._id_token = ""
self._device = device self._device = device
self._called_urls: List[Tuple[int, str]] = [] self._called_urls: List[Tuple[int, str]] = []
self._expires: datetime = datetime.utcnow()
@property @property
def cognito_token(self): def cognito_token(self):
@ -43,6 +48,17 @@ class HonAuth:
def refresh_token(self): def refresh_token(self):
return self._refresh_token return self._refresh_token
def _check_token_expiration(self, hours):
return datetime.utcnow() >= self._expires + timedelta(hours=hours)
@property
def token_is_expired(self) -> bool:
return self._check_token_expiration(self._TOKEN_EXPIRES_AFTER_HOURS)
@property
def token_expires_soon(self) -> bool:
return self._check_token_expiration(self._TOKEN_EXPIRE_WARNING_HOURS)
async def _error_logger(self, response, fail=True): async def _error_logger(self, response, fail=True):
result = "hOn Authentication Error\n" result = "hOn Authentication Error\n"
for i, (status, url) in enumerate(self._called_urls): for i, (status, url) in enumerate(self._called_urls):
@ -72,6 +88,7 @@ class HonAuth:
) as response: ) as response:
self._called_urls.append((response.status, response.request_info.url)) self._called_urls.append((response.status, response.request_info.url))
text = await response.text() text = await response.text()
self._expires = datetime.utcnow()
if not (login_url := re.findall("url = '(.+?)'", text)): if not (login_url := re.findall("url = '(.+?)'", text)):
if "oauth/done#access_token=" in text: if "oauth/done#access_token=" in text:
self._parse_token_data(text) self._parse_token_data(text)
@ -237,12 +254,14 @@ class HonAuth:
await self._error_logger(response, fail=False) await self._error_logger(response, fail=False)
return False return False
data = await response.json() data = await response.json()
self._expires = datetime.utcnow()
self._id_token = data["id_token"] self._id_token = data["id_token"]
self._access_token = data["access_token"] self._access_token = data["access_token"]
return await self._api_auth() return await self._api_auth()
def clear(self): def clear(self):
self._session.cookie_jar.clear_domain(const.AUTH_API.split("/")[-2]) self._session.cookie_jar.clear_domain(const.AUTH_API.split("/")[-2])
self._called_urls = []
self._cognito_token = "" self._cognito_token = ""
self._id_token = "" self._id_token = ""
self._access_token = "" self._access_token = ""

View file

@ -100,14 +100,18 @@ class HonConnectionHandler(HonBaseConnectionHandler):
) -> AsyncIterator: ) -> AsyncIterator:
kwargs["headers"] = await self._check_headers(kwargs.get("headers", {})) kwargs["headers"] = await self._check_headers(kwargs.get("headers", {}))
async with method(*args, **kwargs) as response: async with method(*args, **kwargs) as response:
if response.status in [401, 403] and loop == 0: if (
self._auth.token_expires_soon or response.status in [401, 403]
) and loop == 0:
_LOGGER.info("Try refreshing token...") _LOGGER.info("Try refreshing token...")
await self._auth.refresh() await self._auth.refresh()
async with self._intercept( async with self._intercept(
method, *args, loop=loop + 1, **kwargs method, *args, loop=loop + 1, **kwargs
) as result: ) as result:
yield result yield result
elif response.status in [401, 403] and loop == 1: elif (
self._auth.token_is_expired or response.status in [401, 403]
) and loop == 1:
_LOGGER.warning( _LOGGER.warning(
"%s - Error %s - %s", "%s - Error %s - %s",
response.request_info.url, response.request_info.url,