From 471ea1609fc28890657362b06501fdfe082cddb5 Mon Sep 17 00:00:00 2001 From: "Alan D. Tse" Date: Mon, 1 Mar 2021 19:27:10 -0800 Subject: [PATCH] feat: add support for domain redirection China requires a different auth domain. closes #159 --- Pipfile | 2 +- Pipfile.lock | 144 ++++++++++++++++++++------------------ teslajsonpy/connection.py | 39 ++++++++--- teslajsonpy/const.py | 3 + teslajsonpy/controller.py | 9 +++ teslajsonpy/teslaproxy.py | 4 +- 6 files changed, 122 insertions(+), 79 deletions(-) diff --git a/Pipfile b/Pipfile index 30d37895..f6cab038 100644 --- a/Pipfile +++ b/Pipfile @@ -29,7 +29,7 @@ aiohttp = "*" backoff = "*" beautifulsoup4 = "*" wrapt = "*" -authcaptureproxy = "~=0.5.0" +authcaptureproxy = "~=0.6.0" [pipenv] allow_prereleases = true diff --git a/Pipfile.lock b/Pipfile.lock index 556de073..51a435c9 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "79b8875e3b564b1a2388482732545e8c65ceb37c16bab3bb558d6bc2f1cae971" + "sha256": "dfb9673f9e2f9d2efa88bc7a8bac8ab1894270a213aaa8aa048446d1aa09b144" }, "pipfile-spec": 6, "requires": {}, @@ -71,10 +71,10 @@ }, "authcaptureproxy": { "hashes": [ - "sha256:1f85c839b3ae37d9449704325baf5bdd29f32842701336434961b100c9682f84", - "sha256:64ed20606f70c6513c502af27aad88c6e295797283931db758a43d2f945417b8" + "sha256:396dd27f191b1233e377b7f79afe51bfcb5adce980ac43104addb52b977d5193", + "sha256:b6bcd4ab101adf5fb3167d2350bf9b5b0107f0990579c001bf1d4da4fec84b29" ], - "version": "==0.5.0" + "version": "==0.6.0" }, "backoff": { "hashes": [ @@ -257,10 +257,11 @@ }, "astroid": { "hashes": [ - "sha256:87ae7f2398b8a0ae5638ddecf9987f081b756e0e9fc071aeebdca525671fc4dc", - "sha256:b31c92f545517dcc452f284bc9c044050862fbe6d93d2b3de4a215a6b384bf0d" + "sha256:21d735aab248253531bb0f1e1e6d068f0ee23533e18ae8a6171ff892b98297cf", + "sha256:cfc35498ee64017be059ceffab0a25bedf7548ab76f2bea691c5565896e7128d" ], - "version": "==2.5" + "markers": "python_version >= '3.6'", + "version": "==2.5.1" }, "attrs": { "hashes": [ @@ -374,57 +375,61 @@ }, "coverage": { "hashes": [ - "sha256:03ed2a641e412e42cc35c244508cf186015c217f0e4d496bf6d7078ebe837ae7", - "sha256:04b14e45d6a8e159c9767ae57ecb34563ad93440fc1b26516a89ceb5b33c1ad5", - "sha256:0cdde51bfcf6b6bd862ee9be324521ec619b20590787d1655d005c3fb175005f", - "sha256:0f48fc7dc82ee14aeaedb986e175a429d24129b7eada1b7e94a864e4f0644dde", - "sha256:107d327071061fd4f4a2587d14c389a27e4e5c93c7cba5f1f59987181903902f", - "sha256:1375bb8b88cb050a2d4e0da901001347a44302aeadb8ceb4b6e5aa373b8ea68f", - "sha256:14a9f1887591684fb59fdba8feef7123a0da2424b0652e1b58dd5b9a7bb1188c", - "sha256:16baa799ec09cc0dcb43a10680573269d407c159325972dd7114ee7649e56c66", - "sha256:1b811662ecf72eb2d08872731636aee6559cae21862c36f74703be727b45df90", - "sha256:1ccae21a076d3d5f471700f6d30eb486da1626c380b23c70ae32ab823e453337", - "sha256:2f2cf7a42d4b7654c9a67b9d091ec24374f7c58794858bff632a2039cb15984d", - "sha256:322549b880b2d746a7672bf6ff9ed3f895e9c9f108b714e7360292aa5c5d7cf4", - "sha256:32ab83016c24c5cf3db2943286b85b0a172dae08c58d0f53875235219b676409", - "sha256:3fe50f1cac369b02d34ad904dfe0771acc483f82a1b54c5e93632916ba847b37", - "sha256:4a780807e80479f281d47ee4af2eb2df3e4ccf4723484f77da0bb49d027e40a1", - "sha256:4a8eb7785bd23565b542b01fb39115a975fefb4a82f23d407503eee2c0106247", - "sha256:5bee3970617b3d74759b2d2df2f6a327d372f9732f9ccbf03fa591b5f7581e39", - "sha256:60a3307a84ec60578accd35d7f0c71a3a971430ed7eca6567399d2b50ef37b8c", - "sha256:6625e52b6f346a283c3d563d1fd8bae8956daafc64bb5bbd2b8f8a07608e3994", - "sha256:66a5aae8233d766a877c5ef293ec5ab9520929c2578fd2069308a98b7374ea8c", - "sha256:68fb816a5dd901c6aff352ce49e2a0ffadacdf9b6fae282a69e7a16a02dad5fb", - "sha256:6b588b5cf51dc0fd1c9e19f622457cc74b7d26fe295432e434525f1c0fae02bc", - "sha256:6c4d7165a4e8f41eca6b990c12ee7f44fef3932fac48ca32cecb3a1b2223c21f", - "sha256:6d2e262e5e8da6fa56e774fb8e2643417351427604c2b177f8e8c5f75fc928ca", - "sha256:6d9c88b787638a451f41f97446a1c9fd416e669b4d9717ae4615bd29de1ac135", - "sha256:755c56beeacac6a24c8e1074f89f34f4373abce8b662470d3aa719ae304931f3", - "sha256:7e40d3f8eb472c1509b12ac2a7e24158ec352fc8567b77ab02c0db053927e339", - "sha256:812eaf4939ef2284d29653bcfee9665f11f013724f07258928f849a2306ea9f9", - "sha256:84df004223fd0550d0ea7a37882e5c889f3c6d45535c639ce9802293b39cd5c9", - "sha256:859f0add98707b182b4867359e12bde806b82483fb12a9ae868a77880fc3b7af", - "sha256:87c4b38288f71acd2106f5d94f575bc2136ea2887fdb5dfe18003c881fa6b370", - "sha256:89fc12c6371bf963809abc46cced4a01ca4f99cba17be5e7d416ed7ef1245d19", - "sha256:9564ac7eb1652c3701ac691ca72934dd3009997c81266807aef924012df2f4b3", - "sha256:9754a5c265f991317de2bac0c70a746efc2b695cf4d49f5d2cddeac36544fb44", - "sha256:a565f48c4aae72d1d3d3f8e8fb7218f5609c964e9c6f68604608e5958b9c60c3", - "sha256:a636160680c6e526b84f85d304e2f0bb4e94f8284dd765a1911de9a40450b10a", - "sha256:a839e25f07e428a87d17d857d9935dd743130e77ff46524abb992b962eb2076c", - "sha256:b62046592b44263fa7570f1117d372ae3f310222af1fc1407416f037fb3af21b", - "sha256:b7f7421841f8db443855d2854e25914a79a1ff48ae92f70d0a5c2f8907ab98c9", - "sha256:ba7ca81b6d60a9f7a0b4b4e175dcc38e8fef4992673d9d6e6879fd6de00dd9b8", - "sha256:bb32ca14b4d04e172c541c69eec5f385f9a075b38fb22d765d8b0ce3af3a0c22", - "sha256:c0ff1c1b4d13e2240821ef23c1efb1f009207cb3f56e16986f713c2b0e7cd37f", - "sha256:c669b440ce46ae3abe9b2d44a913b5fd86bb19eb14a8701e88e3918902ecd345", - "sha256:c67734cff78383a1f23ceba3b3239c7deefc62ac2b05fa6a47bcd565771e5880", - "sha256:c6809ebcbf6c1049002b9ac09c127ae43929042ec1f1dbd8bb1615f7cd9f70a0", - "sha256:cd601187476c6bed26a0398353212684c427e10a903aeafa6da40c63309d438b", - "sha256:ebfa374067af240d079ef97b8064478f3bf71038b78b017eb6ec93ede1b6bcec", - "sha256:fbb17c0d0822684b7d6c09915677a32319f16ff1115df5ec05bdcaaee40b35f3", - "sha256:fff1f3a586246110f34dc762098b5afd2de88de507559e63553d7da643053786" - ], - "version": "==5.4" + "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c", + "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6", + "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45", + "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a", + "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03", + "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529", + "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a", + "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a", + "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2", + "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6", + "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759", + "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53", + "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a", + "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4", + "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff", + "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502", + "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793", + "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb", + "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905", + "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821", + "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b", + "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81", + "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0", + "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b", + "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3", + "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184", + "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701", + "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a", + "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82", + "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638", + "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5", + "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083", + "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6", + "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90", + "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465", + "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a", + "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3", + "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e", + "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066", + "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf", + "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b", + "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae", + "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669", + "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873", + "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b", + "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6", + "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb", + "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160", + "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c", + "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079", + "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d", + "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", + "version": "==5.5" }, "cryptography": { "hashes": [ @@ -501,10 +506,11 @@ }, "gitpython": { "hashes": [ - "sha256:8621a7e777e276a5ec838b59280ba5272dd144a18169c36c903d8b38b99f750a", - "sha256:c5347c81d232d9b8e7f47b68a83e5dc92e7952127133c5f2df9133f2c75a1b29" + "sha256:3283ae2fba31c913d857e12e5ba5f9a7772bbc064ae2bb09efafa71b0dd4939b", + "sha256:be27633e7509e58391f10207cd32b2a6cf5b908f92d9cd30da2e514e1137af61" ], - "version": "==3.1.13" + "markers": "python_version >= '3.4'", + "version": "==3.1.14" }, "greenlet": { "hashes": [ @@ -580,6 +586,7 @@ "sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e", "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc" ], + "markers": "python_version >= '3.6' and python_version < '4.0'", "version": "==5.7.0" }, "jeepney": { @@ -599,10 +606,11 @@ }, "keyring": { "hashes": [ - "sha256:9acb3e1452edbb7544822b12fd25459078769e560fa51f418b6d00afaa6178df", - "sha256:9f44660a5d4931bdc14c08a1d01ef30b18a7a8147380710d8c9f9531e1f6c3c0" + "sha256:16927a444b2c73f983520a48dec79ddab49fe76429ea05b8d528d778c8339522", + "sha256:2bc8363ebdd63886126a012057a85c8cb6e143877afa02619ac7dbc9f38a207b" ], - "version": "==22.0.1" + "markers": "python_version >= '3.6'", + "version": "==22.3.0" }, "lazy-object-proxy": { "hashes": [ @@ -813,10 +821,10 @@ }, "pylint": { "hashes": [ - "sha256:81ce108f6342421169ea039ff1f528208c99d2e5a9c4ca95cfc5291be6dfd982", - "sha256:a251b238db462b71d25948f940568bb5b3ae0e37dbaa05e10523f54f83e6cc7e" + "sha256:0e21d3b80b96740909d77206d741aa3ce0b06b41be375d92e1f3244a274c1f8a", + "sha256:d09b0b07ba06bcdff463958f53f23df25e740ecd81895f7d2699ec04bbd8dc3b" ], - "version": "==2.7.1" + "version": "==2.7.2" }, "pyparsing": { "hashes": [ @@ -1085,6 +1093,7 @@ "sha256:2c44efa73b8914dba7807aefd09653ac63c22b5b4ea34f7a80973f418f1a3089", "sha256:c23ac707e8e8aabb825e4d91f8e17247f9cc14b0d64dd9e97be0781e9e525bba" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==4.58.0" }, "twine": { @@ -1149,6 +1158,7 @@ "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80", "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", "version": "==1.26.3" }, "virtualenv": { diff --git a/teslajsonpy/connection.py b/teslajsonpy/connection.py index 22e9a23e..80c0bb34 100644 --- a/teslajsonpy/connection.py +++ b/teslajsonpy/connection.py @@ -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__) @@ -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 @@ -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.""" @@ -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 @@ -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) @@ -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, @@ -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 @@ -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() @@ -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() diff --git a/teslajsonpy/const.py b/teslajsonpy/const.py index 78b78f67..f1915bb0 100644 --- a/teslajsonpy/const.py +++ b/teslajsonpy/const.py @@ -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" diff --git a/teslajsonpy/controller.py b/teslajsonpy/controller.py index c5835b99..683a050c 100644 --- a/teslajsonpy/controller.py +++ b/teslajsonpy/controller.py @@ -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. diff --git a/teslajsonpy/teslaproxy.py b/teslajsonpy/teslaproxy.py index 081839d5..74cbf189 100644 --- a/teslajsonpy/teslaproxy.py +++ b/teslajsonpy/teslaproxy.py @@ -90,7 +90,7 @@ async def test_url( _LOGGER.debug("Success! Oauth code %s for %s captured.", code, username) # 302 redirect return URL(self._callback_url).update_query( - {"code": code, "username": username} + {"code": code, "username": username, "domain": self._host_url.host} ) if resp.content_type == "text/html": text = await resp.text() @@ -183,7 +183,7 @@ async def modify_headers( result = await super().modify_headers(site, request) method = request.method if ( - str(site) == "https://auth.tesla.com/oauth2/v3/authorize/mfa/verify" + str(site.path) == "/oauth2/v3/authorize/mfa/verify" and method == "POST" and not await request.post() ):