forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rework OAuth in Tesla Fleet (home-assistant#123324)
* Rework Oauth * Improve docstrings * Update homeassistant/components/tesla_fleet/oauth.py Co-authored-by: Martin Hjelmare <[email protected]> * review feedback * Add tests for user creds --------- Co-authored-by: Martin Hjelmare <[email protected]>
- Loading branch information
1 parent
00c1a3f
commit f8e1c2c
Showing
6 changed files
with
181 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 4 additions & 58 deletions
62
homeassistant/components/tesla_fleet/application_credentials.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,18 @@ | ||
"""Application Credentials platform the Tesla Fleet integration.""" | ||
|
||
import base64 | ||
import hashlib | ||
import secrets | ||
from typing import Any | ||
|
||
from homeassistant.components.application_credentials import ( | ||
AuthImplementation, | ||
AuthorizationServer, | ||
ClientCredential, | ||
) | ||
from homeassistant.components.application_credentials import ClientCredential | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers import config_entry_oauth2_flow | ||
|
||
from .const import AUTHORIZE_URL, DOMAIN, SCOPES, TOKEN_URL | ||
|
||
AUTH_SERVER = AuthorizationServer(AUTHORIZE_URL, TOKEN_URL) | ||
from .oauth import TeslaUserImplementation | ||
|
||
|
||
async def async_get_auth_implementation( | ||
hass: HomeAssistant, auth_domain: str, credential: ClientCredential | ||
) -> config_entry_oauth2_flow.AbstractOAuth2Implementation: | ||
"""Return auth implementation.""" | ||
return TeslaOAuth2Implementation( | ||
return TeslaUserImplementation( | ||
hass, | ||
DOMAIN, | ||
auth_domain, | ||
credential, | ||
) | ||
|
||
|
||
class TeslaOAuth2Implementation(AuthImplementation): | ||
"""Tesla Fleet API Open Source Oauth2 implementation.""" | ||
|
||
def __init__( | ||
self, hass: HomeAssistant, domain: str, credential: ClientCredential | ||
) -> None: | ||
"""Initialize local auth implementation.""" | ||
self.hass = hass | ||
self._domain = domain | ||
|
||
# Setup PKCE | ||
self.code_verifier = secrets.token_urlsafe(32) | ||
hashed_verifier = hashlib.sha256(self.code_verifier.encode()).digest() | ||
self.code_challenge = ( | ||
base64.urlsafe_b64encode(hashed_verifier).decode().replace("=", "") | ||
) | ||
super().__init__( | ||
hass, | ||
domain, | ||
credential, | ||
AUTH_SERVER, | ||
) | ||
|
||
@property | ||
def extra_authorize_data(self) -> dict[str, Any]: | ||
"""Extra data that needs to be appended to the authorize url.""" | ||
return { | ||
"scope": " ".join(SCOPES), | ||
"code_challenge": self.code_challenge, # PKCE | ||
} | ||
|
||
async def async_resolve_external_data(self, external_data: Any) -> dict: | ||
"""Resolve the authorization code to tokens.""" | ||
return await self._token_request( | ||
{ | ||
"grant_type": "authorization_code", | ||
"code": external_data["code"], | ||
"redirect_uri": external_data["state"]["redirect_uri"], | ||
"code_verifier": self.code_verifier, # PKCE | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
"""Provide oauth implementations for the Tesla Fleet integration.""" | ||
|
||
import base64 | ||
import hashlib | ||
import secrets | ||
from typing import Any | ||
|
||
from homeassistant.components.application_credentials import ( | ||
AuthImplementation, | ||
AuthorizationServer, | ||
ClientCredential, | ||
) | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers import config_entry_oauth2_flow | ||
|
||
from .const import AUTHORIZE_URL, CLIENT_ID, DOMAIN, SCOPES, TOKEN_URL | ||
|
||
|
||
class TeslaSystemImplementation(config_entry_oauth2_flow.LocalOAuth2Implementation): | ||
"""Tesla Fleet API open source Oauth2 implementation.""" | ||
|
||
code_verifier: str | ||
code_challenge: str | ||
|
||
def __init__(self, hass: HomeAssistant) -> None: | ||
"""Initialize open source Oauth2 implementation.""" | ||
|
||
# Setup PKCE | ||
self.code_verifier = secrets.token_urlsafe(32) | ||
hashed_verifier = hashlib.sha256(self.code_verifier.encode()).digest() | ||
self.code_challenge = ( | ||
base64.urlsafe_b64encode(hashed_verifier).decode().replace("=", "") | ||
) | ||
super().__init__( | ||
hass, | ||
DOMAIN, | ||
CLIENT_ID, | ||
"", | ||
AUTHORIZE_URL, | ||
TOKEN_URL, | ||
) | ||
|
||
@property | ||
def name(self) -> str: | ||
"""Name of the implementation.""" | ||
return "Built-in open source client ID" | ||
|
||
@property | ||
def extra_authorize_data(self) -> dict[str, Any]: | ||
"""Extra data that needs to be appended to the authorize url.""" | ||
return { | ||
"scope": " ".join(SCOPES), | ||
"code_challenge": self.code_challenge, # PKCE | ||
} | ||
|
||
async def async_resolve_external_data(self, external_data: Any) -> dict: | ||
"""Resolve the authorization code to tokens.""" | ||
return await self._token_request( | ||
{ | ||
"grant_type": "authorization_code", | ||
"code": external_data["code"], | ||
"redirect_uri": external_data["state"]["redirect_uri"], | ||
"code_verifier": self.code_verifier, # PKCE | ||
} | ||
) | ||
|
||
|
||
class TeslaUserImplementation(AuthImplementation): | ||
"""Tesla Fleet API user Oauth2 implementation.""" | ||
|
||
def __init__( | ||
self, hass: HomeAssistant, auth_domain: str, credential: ClientCredential | ||
) -> None: | ||
"""Initialize user Oauth2 implementation.""" | ||
|
||
super().__init__( | ||
hass, | ||
auth_domain, | ||
credential, | ||
AuthorizationServer(AUTHORIZE_URL, TOKEN_URL), | ||
) | ||
|
||
@property | ||
def extra_authorize_data(self) -> dict[str, Any]: | ||
"""Extra data that needs to be appended to the authorize url.""" | ||
return {"scope": " ".join(SCOPES)} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters