Z-Wave-Me / zwave-smarthome

Z-Way Smart Home UI
GNU General Public License v3.0
57 stars 38 forks source link

No option to stay logged in #301

Open cvtsi2sd opened 1 year ago

cvtsi2sd commented 1 year ago

Using self-hosted ZWave SmartHome UI (so, not through zwave.me proxy), there's no "remember me" checkbox, and all cookies that are set by the login process (most importantly, ZWAYSession and user) are session-bound, so when you close the browser you have to log-in again, which is a pain, especially on mobile. I put a patch on this by putting an nginx reverse proxy in front of it all and adjusting the cookies expiration date to one week, but it's a horrible hack and it seems like this should be supported out of the box.

PoltoS commented 1 year ago

The ZWAYSession cookie is not discarded when you close the tab unless: 1) you login 2) your browser clears cookies between sessions

What is you browser? Does it always forget the cookie?

cvtsi2sd commented 1 year ago

The ZWAYSession cookie that is sent from the server has no expiration set, so it is a session cookie; when you close the browser, it is supposed to be discarded. On desktop Firefox it doesn't really happen (as I keep "session restore" enabled) but with Chromium on Android it's 100% reproducible.

This can be seen replicating the request that Firefox does (by doing "copy with curl" on the network request from developer tools):

> curl -vvvvvvv 'http://my_server:8083/ZAutomation/api/v1/login' --compressed -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: it,en-US;q=0.7,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'ZWAYSessionCookieIgnore: true' -H 'Content-Type: application/json;charset=utf-8' -H 'Origin: http://my_server:8083' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Referer: http://my_server:8083/smarthome/' --data-raw '{"password":"my_password","login":"admin"}'
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 192.168.1.16:8083...
* Connected to my_server (192.168.1.16) port 8083 (#0)
> POST /ZAutomation/api/v1/login HTTP/1.1
> Host: my_server:8083
> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0
> Accept: application/json, text/plain, */*
> Accept-Language: it,en-US;q=0.7,en;q=0.3
> Accept-Encoding: gzip, deflate
> ZWAYSessionCookieIgnore: true
> Content-Type: application/json;charset=utf-8
> Origin: http://my_server:8083
> DNT: 1
> Connection: keep-alive
> Referer: http://my_server:8083/smarthome/
> Content-Length: 47
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Mongoose/6.4
< Content-Type: application/json; charset=utf-8
< X-API-VERSION: 2.0.1
< ZWAYSession: 0400e9ac-3e3e-87d6-d771-813ec7663433
< Set-Cookie: ZWAYSession=0400e9ac-3e3e-87d6-d771-813ec7663433; Path=/
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS
< Access-Control-Allow-Headers: Authorization, Accept-Ranges, Content-Encoding, Content-Length, Content-Range, Content-Type, ETag, X-API-VERSION, Date, Cache-Control, If-None-Match, Content-Language, Accept-Language, X-ZBW-SESSID, ZWAYSession
< Access-Control-Expose-Headers: Authorization, Accept-Ranges, Content-Encoding, Content-Length, Content-Range, Content-Type, ETag, X-API-VERSION, Date, Cache-Control, If-None-Match, Content-Language, Accept-Language, X-ZBW-SESSID, ZWAYSession
< Connection: keep-alive
< Date: Thu, 23 Nov 2023 15:43:39 GMT
< Content-Encoding: deflate
< Content-Length: 369
< 
* Connection #0 to host my_server left intact
{"data":{"id":1,"role":1,"login":"admin","name":"Administrator","lang":"en","dashboard":["Heating_15","ZWayVDev_zway_3-0-67-1","ZWayVDev_zway_2-0-67-1","HTTP_Device_sensorMultilevel_16","HTTP_Device_sensorMultilevel_17","ZWayVDev_zway_5-0-67-1","ZWayVDev_zway_4-0-67-1","ZWayVDev_zway_4-0-49-1","HTTP_Device_sensorMultilevel_18","ZWayVDev_zway_5-0-49-1","ZWayVDev_zway_2-0-49-1","ZWayVDev_zway_3-0-49-1"],"interval":2000,"devices":[],"rooms":[0],"expert_view":true,"hide_all_device_events":false,"hide_system_events":false,"hide_single_device_events":[],"email":"","skin":"","night_mode":true,"beta":false,"uuid":"a8e6c373-7d6a-f1fd-6c19-ac858d1cbdef","sid":"0400e9ac-3e3e-87d6-d771-813ec7663433"},"code":200,"message":"200 OK","error":null}⏎

The interesting bit here is the Set-Cookie: header:

Set-Cookie: ZWAYSession=0400e9ac-3e3e-87d6-d771-813ec7663433; Path=/

as it does not specify an Expires nor a Max-Age field, it is considered a session cookie, as per MDN:

If unspecified, the cookie becomes a session cookie. A session finishes when the client shuts down, after which the session cookie is removed.

Notice that fixing the ZWAYSession cookie expiry (by adjusting the Set-Cookie header through nginx tricks) was not enough: smarthome also requires the user cookie to stay logged in, and that one seems to be set on the client side (as I see that no HTTP response sets it through a Set-Cookie header, but immediately after the login POST response, which is the one that sets the ZWAYSession cookie, the /smarthome GET request already has the other cookies ready).

immagine

immagine

However these cookies get set, still they are only session cookies, as testified by Firefox's cookies view:

immagine

(I got exactly the same data from the Chromium devtools on my phone).

This tracks with the fact that in the sources I see cookies being set with $cookies, which only generates session cookies in the vendored Angular 1.2.28, and still does it by default in later versions, although that seems to be configurable at least.

PoltoS commented 1 year ago

Thank you very much for this details explanation. We will evaluate it and get back to you