edent / Renault-Zoe-API

A basic API for getting information about your Renault Zoe Electric Vehicle.
92 stars 24 forks source link

refresh_token was replaced by xsrfToken #16

Open g-mocken opened 5 years ago

g-mocken commented 5 years ago

Just recently, in the login answer, the refresh_token was replaced by a xsrfToken. As a result, refreshing no longer works like it used to. The login token's typical validity was also reduced from many hours to a few minutes.

Apparently, the new xsrfToken must be transmitted along with the renewal request as HTTPHeaderField "X-XSRF-TOKEN". Then it works.

jamesremuscat commented 5 years ago

Thanks for the research - there's a bit more to it (at least there is now - one gets the impression that they're tinkering with production code somewhat...)

Now when you hit /login, the response includes a Set-Cookie header containing a refreshToken cookie. When you POST to /refresh you'll need to include that refresh token in a Cookie header, as well as the X-XSRF-TOKEN header containing the xsrfToken from the login response body.

I'm sure all this seemed a good idea to someone at the time.

g-mocken commented 5 years ago

Well, for me and the iOS/swift code that I am currently working on, the renewal is still working without explicit such Cookie-Headers. Not sure why, because when I use curl in command line, I do indeed get a "Missing cookie 'refreshToken' " error... I guess the "URLSession" class in iOS just handles the cookies automatically. When I use curl with "-c cookiejar.txt" for the login and with "-b cookiejar.txt" for the renewal, it also succeeds without further explicit data processing or anything on my side.

epenet commented 5 years ago

I've posted a PullRequest relating to this #17

ruditb commented 5 years ago

Yesterday when I refreshed the token I figured out, that the refreshToken from the cookie only works with the token you received with the cookie. If you try to refresh the token you have received from the previous refresh you fail. The reason is, that when you receive a refreshed token they also send a new refreshToken via cookie. As the token has a vlidation time of 15 minutes the refreshToken has a validation time of 24 Hours. So at the very end if you refresh a token you get a new token and a new refreshToken via cookie which you have to use then. The xrsfToken can be reused.

edent commented 5 years ago

I can't accept #17 because I no longer have the vehicle to test with.

If a couple of you test it and report back that it works, I'll merge it.

tobintax commented 5 years ago

Tried it:

Traceback (most recent call last): File "zoe-console.py", line 32, in zeServices = ZEServices(credentials['ZEServicesUsername'], credentials['ZEServicesPassword']) File "/mnt/scripts/Renault-Zoe-API-master/python/shared/zeservices.py", line 25, in init self.accessToken = self.getAccessToken(user, password) File "/mnt/scripts/Renault-Zoe-API-master/python/shared/zeservices.py", line 31, in getAccessToken tokenData = json.load(tokenStorage) File "/usr/lib64/python3.6/json/init.py", line 299, in load parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw) File "/usr/lib64/python3.6/json/init.py", line 354, in loads return _default_decoder.decode(s) File "/usr/lib64/python3.6/json/decoder.py", line 339, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib64/python3.6/json/decoder.py", line 357, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

epenet commented 5 years ago

@tobintax I think it's an issue with your "credentials_token.json" file being empty. I have update the PR to check for JSONDecodeError and treat it the same as FileNotFoundError

tobintax commented 5 years ago

@epenet With your recently changes, the "credentials_token.json" file is not longer empty. Seems ok.

But now I got another error:

Traceback (most recent call last): File "zoe-console.py", line 46, in myRenault = MYRenault(credentials['MyRenaultEmail'], credentials['MyRenaultPassword']) File "/mnt/scripts/Renault-Zoe-API-master/python/shared/myrenault.py", line 20, in init if not self.login(email, password): File "/mnt/scripts/Renault-Zoe-API-master/python/shared/myrenault.py", line 36, in login response = requests.post(url, headers=MYRenault.stealthyHeaders, cookies=self.sessionCookies, data=payload).json() File "/usr/lib/python3.6/site-packages/requests/models.py", line 894, in json return complexjson.loads(self.text, **kwargs) File "/usr/lib64/python3.6/json/init.py", line 354, in loads return _default_decoder.decode(s) File "/usr/lib64/python3.6/json/decoder.py", line 339, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib64/python3.6/json/decoder.py", line 357, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

epenet commented 5 years ago

@tobintax there are two packages: myrenault and zeservices. My fix is only for zeservices (to get battery information). For myrenault (to get total mileage), I cannot run it because I am on Renault-FR and all the URLs are different.

Does it work correctly if you remove MyRenaultEmail and MyRenaultPassword from your credentials file? (Note: they need to be completely removed - not just set to blank)

tobintax commented 5 years ago

@epenet that did it! Thank you very much!

🔋 84% 🚗 91 miles 🔌 Unplugged ⚡ Not charging