Skip to content

Commit 438e1ea

Browse files
author
Boris Fersing
committed
Move oauth2 flow components from pyhilo to hilo. PyHilo had dependencies to HA, this commit allows a transition to the removal of those dependencies. Once the new HA integration is release we'll be able to remove oauth2.py (AuthCodeWithPKCEImplementation)
1 parent 2281a37 commit 438e1ea

File tree

4 files changed

+63
-36
lines changed

4 files changed

+63
-36
lines changed

pyhilo/api.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from aiohttp import ClientSession
1313
from aiohttp.client_exceptions import ClientResponseError
1414
import backoff
15-
from homeassistant.helpers import config_entry_oauth2_flow
1615

1716
from pyhilo.const import (
1817
ANDROID_CLIENT_ENDPOINT,
@@ -67,7 +66,7 @@ def __init__(
6766
self,
6867
*,
6968
session: ClientSession,
70-
oauth_session: config_entry_oauth2_flow.OAuth2Session,
69+
oauth_session,
7170
request_retries: int = REQUEST_RETRY,
7271
log_traces: bool = False,
7372
) -> None:
@@ -98,7 +97,7 @@ async def async_create(
9897
cls,
9998
*,
10099
session: ClientSession,
101-
oauth_session: config_entry_oauth2_flow.OAuth2Session,
100+
oauth_session,
102101
request_retries: int = REQUEST_RETRY,
103102
log_traces: bool = False,
104103
) -> API:

pyhilo/const.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from typing import Final
44

55
import aiohttp
6-
import homeassistant.core
76

87
LOG: Final = logging.getLogger(__package__)
98
DEFAULT_STATE_FILE: Final = "hilo_state.yaml"
@@ -46,7 +45,7 @@
4645

4746

4847
# Request constants
49-
DEFAULT_USER_AGENT: Final = f"PyHilo/{PYHILO_VERSION} HomeAssistant/{homeassistant.core.__version__} aiohttp/{aiohttp.__version__} Python/{platform.python_version()}"
48+
DEFAULT_USER_AGENT: Final = f"PyHilo/{PYHILO_VERSION} aiohttp/{aiohttp.__version__} Python/{platform.python_version()}"
5049

5150

5251
# NOTE(dvd): Not sure how to get new ones so I'm using the ones from my emulator

pyhilo/oauth2.py

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Custom OAuth2 implementation."""
2+
23
import base64
34
import hashlib
45
import os
@@ -8,14 +9,9 @@
89
from homeassistant.core import HomeAssistant
910
from homeassistant.helpers.config_entry_oauth2_flow import LocalOAuth2Implementation
1011

11-
from pyhilo.const import (
12-
AUTH_AUTHORIZE,
13-
AUTH_CHALLENGE_METHOD,
14-
AUTH_CLIENT_ID,
15-
AUTH_SCOPE,
16-
AUTH_TOKEN,
17-
DOMAIN,
18-
)
12+
from pyhilo.const import AUTH_AUTHORIZE, AUTH_CLIENT_ID, AUTH_TOKEN, DOMAIN
13+
14+
from pyhilo.oauth2helper import OAuth2Helper
1915

2016

2117
class AuthCodeWithPKCEImplementation(LocalOAuth2Implementation): # type: ignore[misc]
@@ -34,8 +30,8 @@ def __init__(
3430
AUTH_AUTHORIZE,
3531
AUTH_TOKEN,
3632
)
37-
self._code_verifier = self._get_code_verifier()
38-
self._code_challenge = self._get_code_challange(self._code_verifier)
33+
34+
self.oauth_helper = OAuth2Helper()
3935

4036
# ... Override AbstractOAuth2Implementation details
4137
@property
@@ -46,32 +42,15 @@ def name(self) -> str:
4642
@property
4743
def extra_authorize_data(self) -> dict:
4844
"""Extra data that needs to be appended to the authorize url."""
49-
return {
50-
"scope": AUTH_SCOPE,
51-
"code_challenge": self._code_challenge,
52-
"code_challenge_method": AUTH_CHALLENGE_METHOD,
53-
}
45+
return self.oauth_helper.get_authorize_parameters()
5446

5547
async def async_resolve_external_data(self, external_data: Any) -> dict:
5648
"""Resolve the authorization code to tokens."""
5749
return cast(
5850
dict,
5951
await self._token_request(
60-
{
61-
"grant_type": "authorization_code",
62-
"code": external_data["code"],
63-
"redirect_uri": external_data["state"]["redirect_uri"],
64-
"code_verifier": self._code_verifier,
65-
},
52+
self.oauth_helper.get_token_request_parameters(
53+
external_data["code"], external_data["state"]["redirect_uri"]
54+
)
6655
),
6756
)
68-
69-
# Ref : https://blog.sanghviharshit.com/reverse-engineering-private-api-oauth-code-flow-with-pkce/
70-
def _get_code_verifier(self) -> str:
71-
code = base64.urlsafe_b64encode(os.urandom(40)).decode("utf-8")
72-
return re.sub("[^a-zA-Z0-9]+", "", code)
73-
74-
def _get_code_challange(self, verifier: str) -> str:
75-
sha_verifier = hashlib.sha256(verifier.encode("utf-8")).digest()
76-
code = base64.urlsafe_b64encode(sha_verifier).decode("utf-8")
77-
return code.replace("=", "")

pyhilo/oauth2helper.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import base64
2+
import hashlib
3+
import os
4+
import re
5+
from typing import Any, cast
6+
7+
8+
from pyhilo.const import (
9+
AUTH_AUTHORIZE,
10+
AUTH_CHALLENGE_METHOD,
11+
AUTH_CLIENT_ID,
12+
AUTH_SCOPE,
13+
AUTH_TOKEN,
14+
)
15+
16+
class OAuth2Helper:
17+
"""Custom OAuth2 implementation."""
18+
19+
def __init__(self) -> None:
20+
self._code_verifier = self._get_code_verifier()
21+
self._code_challenge = self._get_code_challenge(self._code_verifier)
22+
23+
# Ref : https://blog.sanghviharshit.com/reverse-engineering-private-api-oauth-code-flow-with-pkce/
24+
def _get_code_verifier(self) -> str:
25+
code = base64.urlsafe_b64encode(os.urandom(40)).decode("utf-8")
26+
return re.sub("[^a-zA-Z0-9]+", "", code)
27+
28+
def _get_code_challenge(self, verifier: str) -> str:
29+
sha_verifier = hashlib.sha256(verifier.encode("utf-8")).digest()
30+
code = base64.urlsafe_b64encode(sha_verifier).decode("utf-8")
31+
return code.replace("=", "")
32+
33+
def get_authorize_parameters(self):
34+
return {
35+
"scope": AUTH_SCOPE,
36+
"code_challenge": self._code_challenge,
37+
"code_challenge_method": AUTH_CHALLENGE_METHOD,
38+
"response_type": "code",
39+
"client_id": AUTH_CLIENT_ID
40+
}
41+
42+
def get_token_request_parameters(self, code, redirect_uri):
43+
return {
44+
"grant_type": "authorization_code",
45+
"code": code,
46+
"redirect_uri": redirect_uri,
47+
"code_verifier": self._code_verifier,
48+
}
49+
50+

0 commit comments

Comments
 (0)