fordpass-ha icon indicating copy to clipboard operation
fordpass-ha copied to clipboard

Integration not working...again

Open 400HPMustang opened this issue 2 years ago • 55 comments

So after a few days of happiness it looks like Ford has decided to change things up again. Not sure if we can continue to use this integration. Here's the logs

This error originated from a custom integration.

Logger: custom_components.fordpass
Source: helpers/update_coordinator.py:223
Integration: Fordpass (documentation, issues)
First occurred: 9:03:06 AM (1 occurrences)
Last logged: 9:03:06 AM

Error fetching fordpass data: Error communicating with FordPass for 1XXXXXXXXXXXXXXX7
This error originated from a custom integration.

Logger: custom_components.fordpass
Source: custom_components/fordpass/__init__.py:188
Integration: Fordpass (documentation, issues)
First occurred: 9:03:06 AM (1 occurrences)
Last logged: 9:03:06 AM

401 Client Error: Unauthorized for url: https://api.mps.ford.com/api/messagecenter/v3/messages

400HPMustang avatar Jun 27 '22 14:06 400HPMustang

Yeah... ford is restricting the token endpoints further. They have removed support for the grant_type=password
I'm still looking for a solution for my Fordpass Widget... I will post any solutions I find here as well

tonesto7 avatar Jun 27 '22 18:06 tonesto7

I occasionally see that error in my logs but it's more the fordpass API having a wobbly with tokens every so often. Usually fixes itself on the next refresh(15mins). In the last 24hrs it did it twice so at the moment it's not really worth worrying about unless it's stopping permanently for anyone.

@tonesto7 I did notice the latest app update changed the auth, be interesting what you find out, luckily the grant type still works for now on the endpoints my integration requires but for how long who knows.

itchannel avatar Jun 27 '22 23:06 itchannel

@itchannel I can confirm that requesting a new token (new logins) is broken and ford uses a new sso portal style login.

If you have an existing refresh token it will continue to get a new token. This just affects new logins at the moment.

tonesto7 avatar Jun 28 '22 16:06 tonesto7

I'm looking into this as well for my homebridge plugin. I've generated authorization codes before and have code that may be useful to this: https://github.com/Brandawg93/homebridge-nest-cam/blob/master/src/login.ts.

https://github.com/Brandawg93/homebridge-nest-cam/blob/master/src/nest/connection.ts#L77

Brandawg93 avatar Jun 28 '22 17:06 Brandawg93

The issue seems to be Ford generates the login service URL per session so there isn't a static login URL anymore. On the ford website the URL is generated here https://www.account.ford.com/etc/fd/fma/bundle.js image

tonesto7 avatar Jun 28 '22 18:06 tonesto7

@itchannel @Brandawg93

image With a body of operation=verify&login-form-type=pwd&username=EMAIL_HERE&password=PASSWORD

The identity_source_id param for me always stays the same with 75d08ad1-510f-468a-b69b-5ebc34f773e3 The state_id is what constantly changes

tonesto7 avatar Jun 28 '22 18:06 tonesto7

That's the same one I get too. More than likely, the state_id is randomly generated.

Brandawg93 avatar Jun 28 '22 18:06 Brandawg93

It's likely to prevent CSRF attacks: https://auth0.com/docs/secure/attack-protection/state-parameters

Bert-R avatar Jun 28 '22 18:06 Bert-R

So they do have an official API but do not mention how to request a token. https://developer.ford.com/apis/fordconnect I used the Contact Us section on the developer homepage to see what they say.

tonesto7 avatar Jun 28 '22 18:06 tonesto7

They probably have to set the business up to handle Oauth, and then you can use their official page.

Brandawg93 avatar Jun 28 '22 18:06 Brandawg93

When you his this endpoint

https://sso.ci.ford.com/v1.0/endpoint/default/authorize?redirect_uri=fordapp://userauthorized&response_type=code&scope=openid&max_age=3600&client_id=9fb503e0-715b-47e8-adfd-ad4b7770f73b&code_challenge=EiBNP3VtgKB3ayeBTzAzvQJlXdvY86JeL4f2X49nDW8%3D&code_challenge_method=S256

you are redirected to

https://sso.ci.ford.com/authsvc/mtfim/sps/authsvc?PolicyId=urn:ibm:security:authentication:asf:basicldapuser&identity_source_id=75d08ad1-510f-468a-b69b-5ebc34f773e3&Target=https%3A%2F%2Fsso.ci.ford.com%2Foidc%2Fendpoint%2Fdefault%2Fauthorize%3FqsId%3D3b15437f-47bc-44a4-b1ea-c871c0ed1c86%26client_id%3D9fb503e0-715b-47e8-adfd-ad4b7770f73b#page=login

This is where the state_id and qsId are generated. Likely to prevent CSRF like @Bert-R mentioned.

The qsId can be found in the URL you are redirected to (second URL above), while the state_id can be found in the html of the page (in the image below).

Screen Shot 2022-06-28 at 1 35 31 PM

Once you submit the login a POST request is made to https://sso.ci.ford.com/authsvc/mtfim/sps/authsvc?identity_source_id=75d08ad1-510f-468a-b69b-5ebc34f773e3&StateId=<state_id> As @tonesto7 mentioned.

Finally, the qsid is used when making the request to the https://sso.ci.ford.com/oidc/endpoint/default/authorize?qsId=<qsId>&client_id=9fb503e0-715b-47e8-adfd-ad4b7770f73b&identity_source_id=75d08ad1-510f-468a-b69b-5ebc34f773e3

That is when the authorization code to fordapp://userauthorized?code=<code> is returned which can be used to get the JWT token.

ianjwhite99 avatar Jun 28 '22 18:06 ianjwhite99

nice find... I can't believe I missed the state_id in the HTML (I was looking for it)

tonesto7 avatar Jun 28 '22 18:06 tonesto7

Ya. Just found that info too. That's the same way I had to do it for homebridge-nest-cam. It's a bit hacky, and makes things more difficult for the end-user unfortunately.

Brandawg93 avatar Jun 28 '22 18:06 Brandawg93

Ford also is validating the cookies as they are coming across to check to make sure the request is actually coming from https://sso.ci.ford.com/. I'm thinking the best solution to this is going to be opening a browser window using selenium, puppeteer or whatever and pulling the cookies & tokens down then using that to make the requests.

It's not going to be the most elegant solution but it might be the only one we have, unfortunately.

ianjwhite99 avatar Jun 28 '22 18:06 ianjwhite99

In my use case, I should be able to encapsulate this all in a nice webview

tonesto7 avatar Jun 28 '22 19:06 tonesto7

I get the need to improve security. Where there's a will there's a way. If they would just release an official API they would have much more control over those that abuse it. Instead of forcing us to come up with these solutions.

tonesto7 avatar Jun 28 '22 19:06 tonesto7

I've done the puppeteer way before. It's pretty horrible.

https://github.com/Brandawg93/homebridge-nest-cam/blob/f40d106620d96972fedb0dd57179d67731cc33aa/src/util/login.ts

Brandawg93 avatar Jun 28 '22 19:06 Brandawg93

I get the need to improve security. Where there's a will there's a way. If they would just release an official API they would have much more control over those that abuse it. Instead of forcing us to come up with these solutions.

Agreed. It would be nice if they added the ability to generate tokens for user accounts or a client_id and client_secret that could be used with their OAuth.

ianjwhite99 avatar Jun 28 '22 19:06 ianjwhite99

I still don't see how we are going to capture the code... We can't capture fordpass:// URL and we can't change it to a custom URL because it throws a CSIAQ0167E error about invalid redirect_uri

tonesto7 avatar Jun 28 '22 19:06 tonesto7

You would need to use something like puppeteer and analyze the response before the redirection and parse the code.

Brandawg93 avatar Jun 28 '22 19:06 Brandawg93

Another snafu is that the Code challenge is not a static value.

tonesto7 avatar Jun 28 '22 19:06 tonesto7

Here's how you do the code: https://github.com/Brandawg93/homebridge-nest-cam/blob/5d174ba8b11400839313c1eb9d875cf8cdb6d2ec/src/nest/connection.ts#L36

Brandawg93 avatar Jun 28 '22 19:06 Brandawg93

The state_id is also in the action attribute in the first URL image

tonesto7 avatar Jun 28 '22 20:06 tonesto7

This will probably help you but not me...

You can use the auth-token and application id from https://www.ford.com/support/vehicle-dashboard.

That way you can do the auth process completely in the browser.

Brandawg93 avatar Jun 28 '22 20:06 Brandawg93

This will probably help you but not me...

You can use the auth-token and application id from https://www.ford.com/support/vehicle-dashboard.

That way you can do the auth process completely in the browser.

Sorry, I'm not following what you mean...

tonesto7 avatar Jun 28 '22 20:06 tonesto7

It looks like they haven't properly locked down oauth between applications, so an auth-token generated by the support website will work for the connect apis.

All I did was:

  1. log into https://www.ford.com/support/vehicle-dashboard
  2. Look in chrome dev console for /users call
  3. Copy auth-token and application-id to usapi status call

You would still need a way to intercept the network calls, but this is much easier than trying to figure the redirect_uri stuff with the fordpass app.

Brandawg93 avatar Jun 28 '22 21:06 Brandawg93

I'm having a hell of a time trying to get the fordapp://userauthorized?code=<code>. I can get all the way to the last request https://sso.ci.ford.com/oidc/endpoint/default/authorize?qsId=<qsId>&client_id=9fb503e0-715b-47e8-adfd-ad4b7770f73b&identity_source_id=75d08ad1-510f-468a-b69b-5ebc34f773e3 using puppeteer but then I get Error: net::ERR_ABORTED.

I'm not sure if its the server blocking me OR if puppeteer is confused because the response is from the fordapp:// URL Scheme.

ianjwhite99 avatar Jun 28 '22 23:06 ianjwhite99

I think i have this almost done with puppeteer... I have to go take care of something but hopefully, I can play with it more tonight.

tonesto7 avatar Jun 28 '22 23:06 tonesto7

Good to see a few people working on it, I agree would be nice if we could just use the official 3rd party API but guessing there's charges associated with it.

itchannel avatar Jun 28 '22 23:06 itchannel

This is a super hacky solution with puppeteer but I figured I'd share.

I was having issues grabbing the fordapp://userauthorized?code=<code>&grant_id=<grant_id>. Puppeteer is confused by the fordapp:// URL Scheme and throws net::ERR_ABORTED.

I attempted to useRequestInterception to try stop the request after successfully hitting the https://sso.ci.ford.com/oidc/endpoint/default/authorize endpoint but I had no luck.

I then however realized that puppeteer logs the reason for the net::ERR_ABORTED to the console. I was able to intercept the message getting logged to the console and grab the fordapp://userauthorized?code=<code>&grant_id=<grant_id> URL scheme successfully using Regex.

Screen Shot 2022-06-28 at 6 55 27 PM

ianjwhite99 avatar Jun 28 '22 23:06 ianjwhite99