Skip to content

Commit

Permalink
fix: decode jwt dates
Browse files Browse the repository at this point in the history
  • Loading branch information
Lash-L committed Mar 17, 2023
1 parent 41eb657 commit cfd170b
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 9 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ packages = [
[tool.poetry.dependencies]
python = "^3.9"
aiohttp = "^3.8.1"
PyJWT = "^2.0"

[tool.poetry.group.dev.dependencies]
pytest = "^7.0"
Expand Down
18 changes: 11 additions & 7 deletions src/southern_company_api/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import List

import aiohttp as aiohttp
import jwt
from aiohttp import ClientSession, ContentTypeError

from southern_company_api.account import Account
Expand Down Expand Up @@ -117,15 +118,17 @@ async def _get_sc_web_token(self) -> str:
raise InvalidLogin()
sc_regex = re.compile(r"NAME='ScWebToken' value='(\S+.\S+.\S+)'", re.IGNORECASE)
sc_data = sc_regex.search(connection["data"]["html"])
self._sc_expiry = datetime.datetime.now() + datetime.timedelta(hours=3)
if sc_data and sc_data.group(1):
if "'>" in sc_data.group(1):
return sc_data.group(1).split("'>")[0]
self._sc = sc_data.group(1).split("'>")[0]
else:
return sc_data.group(1)
self._sc = sc_data.group(1)
else:
self._sc = None
raise NoScTokenFound("Login request did not return a sc token")
sc_decoded = jwt.decode(self._sc, options={"verify_signature": False})
self._sc_expiry = datetime.datetime.fromtimestamp(sc_decoded["exp"])
return self._sc

async def _get_southern_jwt_cookie(self) -> str:
# update to use property
Expand Down Expand Up @@ -203,14 +206,15 @@ async def get_jwt(self) -> str:

# Returning JWT
self._jwt = token
# We can get the exact expiration date from the jwt token, but I don't think it is needed. It should always be
# greater than 3 hours.
self._jwt_expiry = datetime.datetime.now() + datetime.timedelta(hours=3)
jwt_decoded = jwt.decode(self._jwt, options={"verify_signature": False})
self._jwt_expiry = datetime.datetime.fromtimestamp(jwt_decoded["exp"])
return token

async def get_accounts(self) -> List[Account]:
if await self.jwt is None:
raise CantReachSouthernCompany("Can't get jwt. Expired and not refreshed")
raise CantReachSouthernCompany(
f"Can't get jwt. Expired and not refreshed jwt: {self._jwt}"
)
headers = {"Authorization": f"bearer {self._jwt}"}
async with self.session.get(
"https://customerservice2api.southerncompany.com/api/account/"
Expand Down
8 changes: 6 additions & 2 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ async def test_can_authenticate():

@pytest.mark.asyncio
async def test_ga_power_get_sc_web_token():
with patch("southern_company_api.parser.aiohttp.ClientSession.post") as mock_post:
with patch(
"southern_company_api.parser.aiohttp.ClientSession.post"
) as mock_post, patch("src.southern_company_api.parser.jwt.decode"):
mock_post.return_value = MockResponse("", 200, "", ga_power_sample_sc_response)
async with aiohttp.ClientSession() as session:
sca = SouthernCompanyAPI("", "", session)
Expand Down Expand Up @@ -126,7 +128,9 @@ async def test_ga_power_get_jwt():
"src.southern_company_api.parser.aiohttp.ClientSession.get"
) as mock_get, patch(
"src.southern_company_api.parser.SouthernCompanyAPI._get_southern_jwt_cookie"
) as mock_get_cookie:
) as mock_get_cookie, patch(
"src.southern_company_api.parser.jwt.decode"
):
mock_get.return_value = MockResponse("", 200, ga_power_jwt_header, "")
mock_get_cookie.return_value.__aenter__.return_value = ""
async with aiohttp.ClientSession() as session:
Expand Down

0 comments on commit cfd170b

Please sign in to comment.