sdague / mychevy

Python module to interact with my.chevy website for collecting charge data for chevy bolt
Other
50 stars 8 forks source link

login failure #11

Closed tommyjlong closed 4 years ago

tommyjlong commented 4 years ago

Description

Describe what you were trying to get done. This had been working fine in Home Assistant in 0.106.x. Upgraded HA to 0.107 and now this fails. The log below is what I get in Home Assistant, and is the same log when running the debug.py module.

What I Did

python3 debug.py --config ./config.ini

Logging in... this takes a bit
Traceback (most recent call last):
  File "/opt/homeassistant/venv_3.7/lib/python3.7/site-packages/mychevy/mychevy.py", line 218, in get_cars
    _LOGGER.debug("Vehicles: %s", data['data']['vehicleMap'])
KeyError: 'vehicleMap'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "debug.py", line 47, in <module>
    main()
  File "/opt/homeassistant/venv_3.7/lib/python3.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/opt/homeassistant/venv_3.7/lib/python3.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/opt/homeassistant/venv_3.7/lib/python3.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/opt/homeassistant/venv_3.7/lib/python3.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "debug.py", line 32, in main
    page.get_cars()
  File "/opt/homeassistant/venv_3.7/lib/python3.7/site-packages/mychevy/mychevy.py", line 231, in get_cars
    self.account.history))
Exception: 
Something went wrong!

Cookies: <RequestsCookieJar[]>

Content: b'{"messages":[],"serverErrorMsgs":[],"data":{"errorCode":"OCF-101","errorMessage":"Operation not supported","landingUrl":"/login/?invalid","nooKey":null,"ocLeadKey":null}}'

Location: []
DaveLacerte commented 4 years ago

Same thing here

marco-carra commented 4 years ago

This issue is caused by Chevrolet updating their website. MyChevy will need to be updated to work with the new webpage layouts and api.

sdague commented 4 years ago

Unfortunately it looks like gm changed the entire login process. I've been poking at it the last 30 minutes or so, and it's not that straight forward. If anyone wants to figure out how to make the new process work, I'm happy for contributions for the library. However I'm not sure when I might get back to figuring it out.

jaygun commented 4 years ago

After a bit of debugging, I was able to connect to the Chevrolet/OnStar API via Postman. GM now uses Azure AD B2C for authentication, which can be a little cumbersome to authenticate with. Big shout out to the author of this post (https://westerndevs.com/Azure-AD-B2C-Web-Testing/) on Azure AD B2C authentication, which helped greatly with the authentication piece!

Unfortunately I am not a Python developer and do not know where to begin to implement this for myChevy. I am sharing my findings for someone who can use this information to update the integration. Here were the steps followed to connect to the new API.

Step 1: Initial Get Request

Turn off auto-redirect, and send an initial GET request to the following URL:

https://my.chevrolet.com/home

The response should have a Location header with the full URL and query string for the Authorize request. Specifically, we are interested in the nonce value, which will be different each time.

Step 2: AAD Authorize Request

The Location redirect header from the previous step will GET redirect to the following:

https://custlogin.gm.com/gmb2cprod.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1A_SeamlessMigration_SignUpOrSignIn&scope=openid&response_mode=form_post&response_type=id_token&client_id=347218e4-bba6-410c-96ff-c32eb271757f&redirect_uri=https://my.chevrolet.com/oc_login&channel=chevrolet&nonce={{nonce}}&ui_locales=en-US&authCheck=https://my.chevrolet.com/home/?sso=false

The response will contain a SETTINGS JSON object. The important values are the csrf and transId values.

Step 3: Login Request

Using the transId value, build a POST request to the following URL. In the message body, send the following values in x-www-form-urlencoded:

https://custlogin.gm.com/gmb2cprod.onmicrosoft.com/B2C_1A_SeamlessMigration_SignUpOrSignIn/SelfAsserted?tx={{transId}}&p=B2C_1A_SeamlessMigration_SignUpOrSignIn

Once you execute this request you should receive a 200 OK in the following response body. It also important to keep the cookies for additional authentication requests.

Step 4: Generate Auth Code and ID Token

This is fairly straight forward. Now that the session is authenticated, we need to request the code and id_token. Create a new GET request with the following URL:

https://custlogin.gm.com/gmb2cprod.onmicrosoft.com/B2C_1A_SeamlessMigration_SignUpOrSignIn/api/CombinedSigninAndSignup/confirmed?csrf_token={{csrf}}&tx={{tx}}&p=B2C_1A_SeamlessMigration_SignUpOrSignIn

You should receive a basic HTML site with an id_token.

Step 5: Post Request to Site

Create a POST request to the following URL with the id_token value in x-www-form-urlencoded body.

https://my.chevrolet.com/oc_login

At this point, you are now logged in and authorized to call the APIs.

Step 6: Get OnStar Account Data

To call the new API, we will need some account information to build the requests. After a successful login, a GET is called to the following URL to return account data.

https://my.chevrolet.com/api/init/loginSuccessData

From the response, we need to obtain the profileId, vehicle_id, onStarAcctId, vin values.

Step 7: Get OnStar Vehicle Data

Use the values obtained from the previous step and build a GET request to the following URL:

https://my.chevrolet.com/api/{{profileId}}/{{vehicleId}}/onStarAccount/{{onStarAcctId}}/{{vin}}/ovd/maintenanceDetails

In the response, you will should be able to obtain the values needed for Home Assistant.

lukecyca commented 4 years ago

I was able to follow along @jaygun's writeup, as well as the network requests in devtools as I logged in myself, and wrote the following python login function.

https://gist.github.com/lukecyca/7b5714022cb77a734b532bf11421884d

To run this, set the region variable, your login, and password. Once logged in, you can call session.get(...) for any other API endpoint. The session will keep your cookies between requests.

I only tested it with the canada region, but I included urls for the usa region too based on what @jaygun provided.

sdague commented 4 years ago

Thanks so much for this, I've managed to work with into the code and I think it's all working again! Release coming shortly.

tommyjlong commented 4 years ago

Hi, Any update on when this will be available in HA?

sdague commented 4 years ago

It went out in one of the early May releases. It's in current HA.

tommyjlong commented 4 years ago

Excellent! Just tried it and its working. Thanks for this :)