Skip to content

Commit

Permalink
feat: add support for domain redirection
Browse files Browse the repository at this point in the history
China requires a different auth domain.
closes #159
  • Loading branch information
alandtse committed Mar 2, 2021
1 parent e005fcf commit 471ea16
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 79 deletions.
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ aiohttp = "*"
backoff = "*"
beautifulsoup4 = "*"
wrapt = "*"
authcaptureproxy = "~=0.5.0"
authcaptureproxy = "~=0.6.0"

[pipenv]
allow_prereleases = true
144 changes: 77 additions & 67 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 30 additions & 9 deletions teslajsonpy/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@
import aiohttp
from yarl import URL

from teslajsonpy.const import DRIVING_INTERVAL, WEBSOCKET_TIMEOUT
from teslajsonpy.const import (
API_URL,
AUTH_DOMAIN,
DRIVING_INTERVAL,
WEBSOCKET_TIMEOUT,
WS_URL,
)
from teslajsonpy.exceptions import IncompleteCredentials, TeslaException

_LOGGER = logging.getLogger(__name__)
Expand All @@ -51,8 +57,8 @@ def __init__(
self.client_secret: Text = (
"c7257eb71a564034f9419ee651c7d0e5f7" "aa6bfbd18bafb5c5c033b093bb2fa3"
)
self.baseurl: Text = "https://owner-api.teslamotors.com"
self.websocket_url: Text = "wss://streaming.vn.teslamotors.com/streaming"
self.baseurl: Text = API_URL
self.websocket_url: Text = WS_URL
self.api: Text = "/api/1/"
self.expiration: int = expiration
self.access_token = access_token
Expand All @@ -76,6 +82,7 @@ def __init__(
_LOGGER.debug("Connecting with existing access token")
self.websocket = None
self.mfa_code: Text = ""
self.auth_domain: URL = URL(AUTH_DOMAIN)

async def get(self, command):
"""Get data from API."""
Expand Down Expand Up @@ -383,8 +390,22 @@ async def get_authorization_code(
_LOGGER.debug("No email or password for login; unable to login.")
return
url = self.get_authorization_code_link(new=True)
resp = await self.websession.get(url)
resp = await self.websession.get(url.update_query({"login_hint": email}))
html = await resp.text()
if resp.history:
for item in resp.history:
if (
item.status in [301, 302, 303, 304, 305, 306, 307, 308]
and resp.url.host != self.auth_domain.host
):
_LOGGER.debug(
"Detected %s redirect from %s to %s; changing proxy host",
item.status,
item.url.host,
resp.url.host,
)
self.auth_domain = self.auth_domain.with_host(str(resp.url.host))
url = self.get_authorization_code_link()
soup: BeautifulSoup = BeautifulSoup(html, "html.parser")
data = get_inputs(soup)
data["identity"] = email
Expand All @@ -399,7 +420,7 @@ async def get_authorization_code(
if "/mfa/verify" in html:
_LOGGER.debug("Detected MFA request")
mfa_resp = await self.websession.get(
"https://auth.tesla.com/oauth2/v3/authorize/mfa/factors",
self.auth_domain.with_path("/oauth2/v3/authorize/mfa/factors"),
params={"transaction_id": transaction_id},
)
_process_resp(mfa_resp)
Expand Down Expand Up @@ -427,7 +448,7 @@ async def get_authorization_code(
"MFA Code missing", devices=mfa_json["data"]
)
mfa_resp = await self.websession.post(
"https://auth.tesla.com/oauth2/v3/authorize/mfa/verify",
self.auth_domain.with_path("/oauth2/v3/authorize/mfa/verify"),
json={
"transaction_id": transaction_id,
"factor_id": factor_id,
Expand Down Expand Up @@ -475,7 +496,7 @@ def get_authorization_code_link(self, new=False) -> yarl.URL:
"scope": "openid email offline_access",
"state": state,
}
url = yarl.URL("https://auth.tesla.com/oauth2/v3/authorize")
url = self.auth_domain.with_path("/oauth2/v3/authorize")
url = url.update_query(query)
return url

Expand All @@ -494,7 +515,7 @@ async def get_sso_auth_token(self, code):
"redirect_uri": "https://auth.tesla.com/void/callback",
}
auth = await self.websession.post(
"https://auth.tesla.com/oauth2/v3/token",
self.auth_domain.with_path("/oauth2/v3/token"),
data=oauth,
)
return await auth.json()
Expand All @@ -513,7 +534,7 @@ async def refresh_access_token(self, refresh_token):
"scope": "openid email offline_access",
}
auth = await self.websession.post(
"https://auth.tesla.com/oauth2/v3/token",
self.auth_domain.with_path("/oauth2/v3/token"),
data=oauth,
)
return await auth.json()
Expand Down
3 changes: 3 additions & 0 deletions teslajsonpy/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@
DRIVING_INTERVAL = 60 # interval when driving detected
WEBSOCKET_TIMEOUT = 11 # time for websocket to timeout
RELEASE_NOTES_URL = "https://teslascope.com/teslapedia/software/"
AUTH_DOMAIN = "https://auth.tesla.com"
API_URL = "https://owner-api.teslamotors.com"
WS_URL = "wss://streaming.vn.teslamotors.com/streaming"
9 changes: 9 additions & 0 deletions teslajsonpy/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ def set_authorization_code(self, code: Text) -> None:
"""Set authorization code in Connection."""
self.__connection.code = code

def set_authorization_domain(self, domain: Text) -> None:
"""Set authorization domain in Connection."""
if not domain:
return
if self.__connection.auth_domain.host != domain:
self.__connection.auth_domain = self.__connection.auth_domain.with_host(
domain
)

def register_websocket_callback(self, callback) -> int:
"""Register callback for websocket messages.
Expand Down
Loading

0 comments on commit 471ea16

Please sign in to comment.