Skip to content

Commit

Permalink
Merge pull request #215 from sockless-coding/next
Browse files Browse the repository at this point in the history
More authenication logging
  • Loading branch information
sockless-coding authored Jun 24, 2024
2 parents 6b0ef0a + 24d7601 commit 702931e
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 12 deletions.
2 changes: 1 addition & 1 deletion custom_components/panasonic_cc/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"domain": "panasonic_cc",
"name": "Panasonic Comfort Cloud",
"after_dependencies": ["http"],
"version": "1.0.44",
"version": "1.0.45",
"config_flow": true,
"documentation": "https://github.com/sockless-coding/panasonic_cc/",
"dependencies": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ async def authenticate(self, username: str, password: str):

authorization_response = await self._authorize(code_challenge)
authorization_redirect = authorization_response.headers['Location']
_LOGGER.debug("Authorization result, %s", json.dumps({
'redirect': authorization_redirect,
'response': await authorization_response.text()
}))
# check if the user can skip the authentication workflows - in that case,
# the location is directly pointing to the redirect url with the "code"
# query parameter included
Expand Down Expand Up @@ -98,6 +102,7 @@ async def _authorize(self, challenge) -> aiohttp.ClientResponse:
# AUTHORIZE
# --------------------------------------------------------------------
state = generate_random_string(20)
_LOGGER.debug("Requesting authorization, %s", json.dumps({'challenge': challenge, 'state': state}))

response = await self._client.get(
f'{BASE_PATH_AUTH}/authorize',
Expand All @@ -122,22 +127,24 @@ async def _authorize(self, challenge) -> aiohttp.ClientResponse:


async def _login(self, authorization_response: aiohttp.ClientResponse, username, password):
_LOGGER.debug("Trying to log in")

state = get_querystring_parameter_from_header_entry_url(
authorization_response, 'Location', 'state')
location = authorization_response.headers['Location']
_LOGGER.debug("Following authorization redirect, %s", json.dumps({'url': f"{BASE_PATH_AUTH}/{location}", 'state': state}))
response = await self._client.get(
f"{BASE_PATH_AUTH}/{location}",
allow_redirects=False)
await check_response(response, 'authorize_redirect', 200)
_LOGGER.debug("Authorization redirect response, %s", json.dumps({ 'headers': dict(response.headers), 'cookies': response.cookies.output() }))

# get the "_csrf" cookie
csrf = response.cookies['_csrf']

# -------------------------------------------------------------------
# LOGIN
# -------------------------------------------------------------------

_LOGGER.debug("Authenticating with username and password, %s", json.dumps({'csrf':csrf,'state':state}))
response = await self._client.post(
f'{BASE_PATH_AUTH}/usernamepassword/login',
headers={
Expand Down Expand Up @@ -167,13 +174,15 @@ async def _login(self, authorization_response: aiohttp.ClientResponse, username,
# -------------------------------------------------------------------

# get wa, wresult, wctx from body
soup = BeautifulSoup(await response.text(), "html.parser")
response_text = await response.text()
_LOGGER.debug("Authentication response, %s", json.dumps({'html':response_text}))
soup = BeautifulSoup(response_text, "html.parser")
input_lines = soup.find_all("input", {"type": "hidden"})
parameters = dict()
for input_line in input_lines:
parameters[input_line.get("name")] = input_line.get("value")


_LOGGER.debug("Callback with parameters, %s", json.dumps(parameters))
response = await self._client.post(
url=f"{BASE_PATH_AUTH}/login/callback",
data=parameters,
Expand All @@ -189,11 +198,14 @@ async def _login(self, authorization_response: aiohttp.ClientResponse, username,
# ------------------------------------------------------------------

location = response.headers['Location']
_LOGGER.debug("Callback response, %s", json.dumps({'redirect':location, 'html': await response.text()}))

response = await self._client.get(
f"{BASE_PATH_AUTH}/{location}",
allow_redirects=False)
await check_response(response, 'login_redirect', 302)
location = response.headers['Location']
_LOGGER.debug("Callback redirect, %s", json.dumps({'redirect':location, 'html': await response.text()}))

return get_querystring_parameter_from_header_entry_url(
response, 'Location', 'code')
Expand Down
21 changes: 14 additions & 7 deletions custom_components/panasonic_cc/pcomfortcloud/panasonicsettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,20 @@ async def _load(self):
try:
async with aiofiles.open(self._fileName) as json_file:
data = json.loads(await json_file.read())
self._version = data[SETTING_VERSION]
self._versionDate = date.fromisoformat(data[SETTING_VERSION_DATE])
self._access_token = data[SETTING_ACCESS_TOKEN]
self._access_token_expires = data[SETTING_ACCESS_TOKEN_EXPIRES]
self._refresh_token = data[SETTING_REFRESH_TOKEN]
self._clientId = data[SETTING_CLIENT_ID]
self._scope = data[SETTING_SCOPE]
if SETTING_VERSION in data:
self._version = data[SETTING_VERSION]
if SETTING_VERSION_DATE in data:
self._versionDate = date.fromisoformat(data[SETTING_VERSION_DATE])
if SETTING_ACCESS_TOKEN in data:
self._access_token = data[SETTING_ACCESS_TOKEN]
if SETTING_ACCESS_TOKEN_EXPIRES in data:
self._access_token_expires = data[SETTING_ACCESS_TOKEN_EXPIRES]
if SETTING_REFRESH_TOKEN in data:
self._refresh_token = data[SETTING_REFRESH_TOKEN]
if SETTING_CLIENT_ID in data:
self._clientId = data[SETTING_CLIENT_ID]
if SETTING_SCOPE in data:
self._scope = data[SETTING_SCOPE]
_LOGGER.debug("Loaded settings from '%s'", self._fileName)
except Exception as ex:
_LOGGER.warning("Failed to loaded settings from '%s'", self._fileName, exc_info = ex)
Expand Down

0 comments on commit 702931e

Please sign in to comment.