KalenXI / NissanConnect

Python program for remote controlling Nissan cars via NissanConnect Services
The Unlicense
10 stars 0 forks source link

404 for https://mobile.telematics.net/login/token #5

Open rahilp opened 1 year ago

rahilp commented 1 year ago

Thanks again for this project! I'm trying to use it, however I'm getting a 404 returned for the https://mobile.telematics.net/login/token --- do you know if the login url on line 22 has changed?

def login(self, username, password):
        loginuser = 'NISNNAVCS/' + username
        r = requests.post('https://mobile.telematics.net/login/token', headers={'CV-APPID': 'cv.nissan.connect.us.android.25'}, json={'username': loginuser, 'password': password})
        print(r.json())
        return r.json()

Here is the full error being returned:

<Response [404]>
Traceback (most recent call last):
  File "/Users/rahil.pirani/Library/Python/3.9/lib/python/site-packages/requests/models.py", line 971, in json
    return complexjson.loads(self.text, **kwargs)
  File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/rahil.pirani/Desktop/nissan.py", line 99, in <module>
    nissan = Nissan('https://prd.api.telematics.net/m/', args.user, args.password)
  File "/Users/rahil.pirani/Library/Python/3.9/lib/python/site-packages/uplink/builder.py", line 243, in new_init
    init(self, *args, **kwargs)
  File "/Users/rahil.pirani/Desktop/nissan.py", line 11, in __init__
    self.api_key = self.login(username, password)
  File "/Users/rahil.pirani/Desktop/nissan.py", line 24, in login
    print(r.json())
  File "/Users/rahil.pirani/Library/Python/3.9/lib/python/site-packages/requests/models.py", line 975, in json
    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
EnragedMagician commented 1 year ago

I have also gotten a 404 when trying the POST in Postman. It seems the URL is no longer valid.

On a side note: I do see a lot of DNS lookups from the Nissan Connect app (iOS) to the following hostnames: idm.cv000-telematics.net nissan.cv000-telematics.net vns.cv000-telematics.net cps.cv000-telematics.net rts.cv000-telematics.net am.cv000-telematics.net

fenty17 commented 1 year ago

Also following this as it’s on my list of things to test out soon.

KalenXI commented 1 year ago

Nissan switched to a completely new API with version 6 of their app. I reversed engineered the new API See here but haven’t had the time or interest to update the script.

rahilp commented 1 year ago

Thanks @KalenXI ! I completely understand and appreciate the work you’ve put into it so far. Happy to help out with the Python script… but would be great if you could share the postman collection for the authentication to give me a head start.

KalenXI commented 1 year ago

@rahilp Here's the collection. The basic flow is to obtain an auth token from the https://am.cv000-telematics.net/auth/oauth2/realms/root/realms/nissanus/access_token endpoint using the client ID and username/pass that's hard-coded into the app.

Then send a request to https://nissan.cv000-telematics.net/login/token with the auth token in the header, and your username/pass in the body in JSON format to get an ID token.

Then take the auth token from the first step, and the ID token from the second step, along with the VIN for the car and send that to one of the command end points: https://rts.cv000-telematics.net/telematicsservices/v0/vehicles/remote-horn-and-lights

Nissan.postman_collection.json.zip

fenty17 commented 1 year ago

I was also going to ask about the Postman collection. Thanks @KalenXI ! I don’t have much faith in Nissan to not screw things up again before too long, but you never know.

jpeden commented 1 year ago

@KalenXI any chance you (or anyone else here) can verify the approach from your blog post/postman still works? I've gotten as far as getting id_token back, but requests are returning { "status": 403, "code": "TP4031", "message": "Forbidden. Not Authorized", "language": "en-US", "faultInfo": [ "Forbidden. Not Authorized" ] }

I get the same with "id_token" intentionally changed to a different value, which makes me think I'm missing a step in copying value from step 2 to 3?

I'm really hoping to be able to pull battery/charging status from my new Ariya into Home Assistant if I an get a repeatable query working...

KalenXI commented 1 year ago

@jpeden Unless something’s changed recently I believe Nissan’s electric vehicles use an entirely different protocol and app.

jpeden commented 1 year ago

@jpeden Unless something’s changed recently I believe Nissan’s electric vehicles use an entirely different protocol and app.

The Ariya is using "Nissan Connect Services" app (not "Nissan Connect EV" that the Leaf uses), so should be same protocol here. I've confirmed the Android app is using same hosts and structure appears to be the same. Working now to capture some request logs to see if I can identify what's different from your request flow.

gilliginsisland commented 1 year ago

@KalenXI thanks for the work you did reverse engineering both the previous api and the new one. I took your postman collection and it turns out that double authentication isn't needed.

When calling https://nissan.cv000-telematics.net/login/token to get your id_token and access_token, you do not need to pass in an Authentication header, you only need the CV (CV-Correlation-Id, CV-APPID, CV-Tenant-Id) headers. That means that the first call to https://am.cv000-telematics.net/auth/oauth2/realms/root/realms/nissanus/access_token to get an access_token is not needed.

All endpoints on nissan.cv000-telematics.net other than login/token need an access token from am.cv000-telematics.net, but login/token does not.

When sending commands to https://rts.cv000-telematics.net/telematicsservices/v0/vehicles/* you only need the CV headers, vin header, and the id_token and Bearer access_token from the login/token endpoint. You do not need an access_token from am.cv000-telematics.net, the one from nissan.cv000-telematics.net is enough.

This means that it's trivial to fix the script, since you only need to make one login call to get both the id_token and the access_token. Also all the endpoints are the same.

fenty17 commented 1 year ago

@gilliginsisland - thanks for sharing this info. I gave up trying to get this to work but I'm sure me and others are still interested in a working solution. Based on your discoveries, would you be willing to share a revised Postman collection or similar to help us along?

gilliginsisland commented 1 year ago

@gilliginsisland - thanks for sharing this info. I gave up trying to get this to work but I'm sure me and others are still interested in a working solution. Based on your discoveries, would you be willing to share a revised Postman collection or similar to help us along?

I'll do you one better. I made a gist with a quick script that uses the new api, and is similar to this one.

https://gist.github.com/gilliginsisland/697633182d290cdec7e034d72e7a6771

Use it like this: nissan-connect.py --username=john.doe@example.com --password=my-super-secret-pass --vin=xxxxxxxx post remote-engine --pin=123456 START

nissan-connect.py --username=john.doe@example.com --password=my-super-secret-pass --vin=xxxxxxxx post remote-engine --pin=123456 STOP

You can also check the status of the last command sent with: nissan-connect.py --username=john.doe@example.com --password=my-super-secret-pass --vin=xxxxxxxx get remote-engine

Or all commands sent with: nissan-connect.py --username=john.doe@example.com --password=my-super-secret-pass --vin=xxxxxxxx get remote-service-history

See all the endpoints and values supported with: nissan-connect.py --username=john.doe@example.com --password=my-super-secret-pass --vin=xxxxxxxx post -h

Also there is an exposed swagger api that documents the api here https://prd.api.telematics.net/m/remote https://prd.api.telematics.net/m/monitor https://prd.api.telematics.net/m/location https://prd.api.telematics.net/m/information https://prd.api.telematics.net/m/nissan

Those swagger docs are for the older api, but most of the endpoints are similar in the new api, but I haven't been able to figure out if there is a similar swagger api exposed.

fenty17 commented 1 year ago

Brilliant! Thanks so much for taking the time to share. Looking forward to trying this soon. Fingers crossed Nissan don't change everything again anytime soon.

fenty17 commented 1 year ago

@gilliginsisland - I only just got round to trying your script and receive the following error:

Traceback (most recent call last): File "/opt/nissan-connect.py", line 123, in <module> main() File "/opt/nissan-connect.py", line 115, in main client = NissanClient(NissanAuth(args.username, args.password), args.vin) File "/opt/nissan-connect.py", line 41, in __init__ r.raise_for_status() File "/usr/lib/python3/dist-packages/requests/models.py", line 943, in raise_for_status raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://nissan.cv000-telematics.net/login/token

Has Nissan shut things down again or does it still work for you? I notice the swagger docs are no longer accessible either. Also wondering whether the US auth header URLs are an issue given I'm UK-based?

gilliginsisland commented 1 year ago

@fenty17 That's weird, it does still work for me. I'm not sure if the api for UK is different, the original version of this script didn't do anything different for the UK vs US, so I'm not sure if there is a different UK api.

I have actually made this into a home assistant custom_component that tracks the vehicle location via GPS, as well as the door, hatch, and engine hood open / close statuses, tire pressure, and also allows remote door lock / unlock and lock status.

https://github.com/gilliginsisland/hass-nissan-connect

fenty17 commented 1 year ago

Wow. Kudos to you! It may well be something I'm doing wrong but given my use case is for Home Assistant integration I will be sure to try out your custom component. Have you had any UK testers of your HA component yet?