11"""Custom OAuth2 implementation."""
2+
23import base64
34import hashlib
45import os
89from homeassistant .core import HomeAssistant
910from 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+ from pyhilo .oauth2helper import OAuth2Helper
1914
2015
2116class AuthCodeWithPKCEImplementation (LocalOAuth2Implementation ): # type: ignore[misc]
@@ -34,8 +29,8 @@ def __init__(
3429 AUTH_AUTHORIZE ,
3530 AUTH_TOKEN ,
3631 )
37- self . _code_verifier = self . _get_code_verifier ()
38- self ._code_challenge = self . _get_code_challange ( self . _code_verifier )
32+
33+ self .oauth_helper = OAuth2Helper ( )
3934
4035 # ... Override AbstractOAuth2Implementation details
4136 @property
@@ -46,32 +41,15 @@ def name(self) -> str:
4641 @property
4742 def extra_authorize_data (self ) -> dict :
4843 """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- }
44+ return self .oauth_helper .get_authorize_parameters ()
5445
5546 async def async_resolve_external_data (self , external_data : Any ) -> dict :
5647 """Resolve the authorization code to tokens."""
5748 return cast (
5849 dict ,
5950 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- },
51+ self .oauth_helper .get_token_request_parameters (
52+ external_data ["code" ], external_data ["state" ]["redirect_uri" ]
53+ )
6654 ),
6755 )
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 ("=" , "" )
0 commit comments