Skip to content

Commit

Permalink
Merge pull request #754 from 0x3dlux/master
Browse files Browse the repository at this point in the history
Accomodate for Stellantis' Jan 23 OAuth changes
  • Loading branch information
flobz committed Feb 19, 2024
2 parents c67286a + badda49 commit 35a5ea5
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 11 deletions.
2 changes: 1 addition & 1 deletion psa_car_controller/psa/connected_car_api/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def __init__(self):
# Debug file location
self.logger_file = None
# Debug switch
self.debug = False
self.debug = True

# SSL/TLS verification
# Set this to false to skip verifying SSL certificate when calling API
Expand Down
7 changes: 6 additions & 1 deletion psa_car_controller/psa/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@
"program3": {"day": [0, 0, 0, 0, 0, 0, 0], "hour": 34, "minute": 7, "on": 0},
"program4": {"day": [0, 0, 0, 0, 0, 0, 0], "hour": 34, "minute": 7, "on": 0}
}
AUTHORIZE_SERVICE = "https://api.mpsa.com/api/connectedcar/v2/oauth/authorize"
AUTHORIZE_SERVICE = {"clientsB2COpel": "https://idpcvs.opel.com/am/oauth2/authorize",
"clientsB2CPeugeot": "https://idpcvs.peugeot.com/am/oauth2/authorize",
"clientsB2CCitroen": "https://idpcvs.citroen.com/am/oauth2/authorize",
"clientsB2CDS": "https://idpcvs.driveds.com/am/oauth2/authorize",
"clientsB2CVauxhall": "https://idpcvs.vauxhall.co.uk/am/oauth2/authorize"
}
REMOTE_URL = "https://api.groupe-psa.com/connectedcar/v4/virtualkey/remoteaccess/token?client_id="
BRAND = {"com.psa.mym.myopel": {"realm": "clientsB2COpel", "brand_code": "OP", "app_name": "MyOpel"},
"com.psa.mym.mypeugeot": {"realm": "clientsB2CPeugeot", "brand_code": "AP", "app_name": "MyPeugeot"},
Expand Down
30 changes: 28 additions & 2 deletions psa_car_controller/psa/oauth.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import logging
import hashlib
import secrets
import base64
from typing import Tuple

from http import HTTPStatus
from typing import Optional

Expand All @@ -22,8 +27,29 @@ def _grant_password_request_realm(self, login: str, password: str, realm: str) -
return {"grant_type": 'password', "username": login, "scope": ' '.join(self.service_information.scopes),
"password": password, "realm": realm}

def init_with_user_credentials_realm(self, login: str, password: str, realm: str):
self._token_request(self._grant_password_request_realm(login, password, realm), True)
def generate_sha256_pkce(self, length: int) -> Tuple[str, str]:
if not (43 <= length <= 128):
raise ValueError("Invalid length: %d" % length)
verifier = secrets.token_urlsafe(length)
encoded = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode('ascii')).digest())
challenge = encoded.decode('ascii')[:-1]
return verifier, challenge

def init_with_brand_country_code(self, brand: str, country_code: str):
redir_uri = "mym" + brand.lower() + "://oauth2redirect/" + country_code.lower()
code_verifier, code_challenge = self.generate_sha256_pkce(64)
url = self.generate_authorize_url(redir_uri, secrets.token_urlsafe(16),
code_challenge=code_challenge, code_challenge_method="S256")

logger.info("Now login to this URL in a browser: %s", url)

ret = ""
while len(ret) != 36:
ret = input("\nCopy+paste the resulting mymXX-code (in F12 > Network, " \
"when you hit the final OK button, 36 chars, UUID format): ")

self._token_request({ "grant_type": 'authorization_code', "code": ret,
"redirect_uri": redir_uri, "code_verifier": code_verifier}, False)

@staticmethod
def _is_token_expired(response: Response) -> bool:
Expand Down
4 changes: 2 additions & 2 deletions psa_car_controller/psa/setup/app_decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ def firstLaunchConfig(package_name, client_email, client_password, country_code,
# Psacc
psacc = PSAClient(None, apk_parser.client_id, apk_parser.client_secret,
None, customer_id, BRAND[package_name]["realm"],
country_code)
psacc.connect(client_email, client_password)
country_code, BRAND[package_name]["brand_code"])
psacc.connect()
psacc.save_config(name=config_prefix + "config.json")
res = psacc.get_vehicles()

Expand Down
9 changes: 5 additions & 4 deletions psa_car_controller/psacc/application/psa_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@


class PSAClient:
def connect(self, user, password):
self.manager.init_with_user_credentials_realm(user, password, self.realm)
def connect(self):
self.manager.init_with_brand_country_code(self.brand, self.country_code)

# pylint: disable=too-many-arguments
def __init__(self, refresh_token, client_id, client_secret, remote_refresh_token, customer_id, realm, country_code,
proxies=None, weather_api=None, abrp=None, co2_signal_api=None):
brand=None, proxies=None, weather_api=None, abrp=None, co2_signal_api=None):
self.realm = realm
self.service_information = ServiceInformation(AUTHORIZE_SERVICE,
self.service_information = ServiceInformation(AUTHORIZE_SERVICE[self.realm],
realm_info[self.realm]['oauth_url'],
client_id,
client_secret,
Expand All @@ -60,6 +60,7 @@ def __init__(self, refresh_token, client_id, client_secret, remote_refresh_token
self._record_enabled = False
self.weather_api = weather_api
self.country_code = country_code
self.brand = brand
self.info_callback = []
self.info_refresh_rate = 120
if abrp is None:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ include = [

[tool.poetry.dependencies]
python = ">=3.7.2, <4.0.0"
paho-mqtt = ">=1.5.0"
paho-mqtt = ">=1.5.0, <2.0.0"
dash = ">=2.9.0, <3.0.0"
dash-daq = "^0.5.0"
plotly = ">=5"
Expand Down

0 comments on commit 35a5ea5

Please sign in to comment.