supergeorg / Grocy-SwiftUI

A client for Grocy for macOS and iOS, written with SwiftUI
GNU General Public License v3.0
182 stars 19 forks source link

Support for HASS API ingress #17

Open QuiGonSwag opened 3 years ago

QuiGonSwag commented 3 years ago

In order to access instances that are hosted through home assistant you need to leverage the hass ingress api which requires another auth key. Would this be something you could support?

See the issue that solves the same issue for the android equivalent app: https://github.com/patzly/grocy-android/issues/249

supergeorg commented 3 years ago

I will look into it. To test it, I will have to setup this on my server, but it will be interesting to do so.

For support, I don't know how hard it is. If it is just some other login method, it should be fine. If it requires big changes to the networking, I will consider if the work is worth it. Also it doesn't seem ready on Android (Issue is open), maybe it is harder than I think it is.

Lemonadel commented 3 years ago

It would be great to have it working. I just faced this problem because even changing ports in HASSIO integration settings and disabling ssl does not help to log in

supergeorg commented 3 years ago

Ok, I have set up a Hass.io instance. The problems seems to be that I need two? authentications, one for HASS, one for Grocy. But for now, I get HTTP Error 401, even with a long-term API key. So this still needs some work to do.

supergeorg commented 3 years ago

Is there a reason to use ingress? I haven't understood the need for Ingress and how the add-on works. Just set a port and it works fine (e.g. http://homeassistant.local:PORT).

It seems like quite some work, since I need to track a separate Authentication and Proxy. Also there has to be an Ingress Session Cookie created and tracked. So the user has to create a long-lived Token as well as a Grocy API key (which also includes the HASS proxy path) and Import both it via QR. I don't know how long it takes, but it needs some thinking to be done right (only small changes in backend code and no regressions for normal users). So this will be in a later update (maybe 1.1), but hopefully before the iOS 15 one.

dominiczedler commented 3 years ago

Hi, I just found this app via grocy.info :-) I'm one of the developers of patzly/grocy-android and I'm very happy that there is an iOS app now which my parents with iOS devices can use, thank you.

I think the solution with port opening has some disadvantages: HTTPS has to be handled manually and I think the port is not reachable with the Nabu Casa service. Besides that, some people wrote me that they don't want to open an additional port on their server (don't ask me why).

So the clean solution is Ingress but it is really not easy to implement in an app. In our Android app (ingress auth implementation is a bit hacky there) we don't work with session cookies, only with the session token:

  1. Has token stored and it is not older than one minute? -> make API request
  2. Has no token stored? -> request a new token with POST: /api/hassio/ingress/session
  3. Has token stored and it is older than one minute? -> validate token with POST: /api/hassio/ingress/validate_session

The long-lived access token is in every request header: Authorization: Bearer TOKEN We chose "one minute" because I saw that on the Home Assistant webpage there is a validate_session request every minute. You can ask me anytime if you have questions, just ping me with @.

supergeorg commented 3 years ago

Thank you for the explanation. Your app serves as a great inspiration for me and has interesting solutions for implementing design and function of the app.

Your described handling of Ingress seems to be simple and implementable without big amounts of new code. I will try it and give feedback on it.

xBourner commented 3 years ago

Just want to bump this. I can't get your app running with ingress or even with a new port (with and without ssl). It works with the app Pantry Party but yours looks better and is available in german.

It would be much easier and user friendly to get it working with ingress but it sounds hard to manage it. So i would like to get your app running like you mentioned above. Do you have any how to's to get it working with port opening?

dominiczedler commented 3 years ago

@xBourner There is a short how-to for that on the FAQ page of Grocy Android, it should be the same steps for this app here: https://github.com/patzly/grocy-android/blob/master/FAQ.md#user-content-faq4 I hope this works for you.

xBourner commented 3 years ago

@MrJohnZoidberg did it like this and i can access the login page via https://my.name.org:4444 But if i scan a QR Code it will send me to https://my.name.org/hassio_ingress/.... If i type in https://my.name.org:4444 in the app it connects but it shows "No connection to Server" in every section

EDIT: i think this has something to do with a new update of the grocy addon (https://github.com/hassio-addons/addon-grocy/issues/208) others are having the same problem and i think the addon needs to be fixed instead of the app.

supergeorg commented 3 years ago

I have replicated the progress for Hass Ingress with an API tool and am searching for a good way to implement this. The tricky point is that it first needs the session cookie, and afterwards get the normal request. This case would be a perfect fit for the async await pattern in iOS 15, but I'm looking for another way to get it working now. This has top priority for now, as soon as I find time to find the right solution.

supergeorg commented 3 years ago

Ok, it should work now. Please test the new version (1.2.0) and if it works for you. I tested this on a local system and it worked fine. But I am not 100% confident that it works as well as a direct access.

Kakise commented 3 years ago

Here it just says "hassError", what's your exact configuration ?

Error: hassError(error:
Grocy_Mobile.APIError.hassError(error:
Grocy_Mobile.APIError.unsuccessful))
supergeorg commented 3 years ago

This error means that the token request was unsuccessful. Please check that the home assistant URL (the part before /api) and Bearer Token is valid. I will need to throw better error messages in the future.

Kakise commented 3 years ago

This error means that the token request was unsuccessful. Please check that the home assistant URL (the part before /api) and Bearer Token is valid. I will need to throw better error messages in the future.

Works perfectly now ! Maybe adding to the docs that you need the urls with the QR Code would be great ?

The home assistant url should always be the base url and the grocy server url should be the one from the api QR Code with /api/ added right after the base url

xBourner commented 3 years ago

home assistant URL (the part before /api)

I don't get it. When i want to connect it with ingress what do i have to type into the four fields?

Server-URL? API Key? API Path for HA? Token for HA?

I don't have any URL with api when accessing grocy or scanning any QR Code. My URL looks like https://xxx.name.org/hassio/ingress/a0d7b954_grocy

Am i doing something wrong?

@supergeorg any help with this?

Lemonadel commented 3 years ago

I also look for a small tutorial. I created API Key in Ingress, created one in HomeAssistant also, but I don’t know what is API Path for HA. SSL is disabled, port has been changed and is reachable from browser (not like before error 401)

supergeorg commented 3 years ago

I will write a small tutorial this weekend and make the app a bit more explaining.

You need the Grocy URL (which is accessed via Ingress) as well as the Grocy API key. So much for normal login. But home assistant needs another key, which allows the user to log in. This is the Long Time Bearer Token which can be generated in the Home Assistant settings. The last part is the Home Assistant server URL. I will check if it is needed (since it should be the trunk of the Grocy Ingress URL). With this URL, you can access the API of Home Assistant, found under $HASSURL/api This means there are two logins, one for Grocy (URL+Key), one for Home Assistant (URL+Key).

xBourner commented 3 years ago

@supergeorg Thanks for your reply. I will wait for your tutorial. I think my problem is the Grocy URL. Is it the URL when scan the QR Code in grocy itself (api key)? Or is it the URL when accessing grocy over my browser or something else?

Grocy API Key should be the key which you get from QR Code api keys in grocy? HA URL is my URL with /api/ at the end? and HA Token is the long living token i created under my user?

does the user who uses grocy and the one which made the long living token in HA need to be named the same?

xBourner commented 3 years ago

@supergeorg works great now. 1.2.1 made it work for me. thank you!

AssassinScript commented 3 years ago

Yay it’s working :) but partly… Looks like I do something wrong 😅 App connects in local internet to Raspi 4 with HAOS, however for most of options I have “no connection to server”: Quick scan - no connection Stock overview - no connection Shopping list - working allows to create new products, these are also created in HAOS Master data - I can do everything here

Environment:

All of them have default settings, not played with ssl yet, no changed ports. If so I can send you logs :) anyways thank you for this update!

Kakise commented 3 years ago

Yay it’s working :) but partly… Looks like I do something wrong 😅 App connects in local internet to Raspi 4 with HAOS, however for most of options I have “no connection to server”: Quick scan - no connection Stock overview - no connection Shopping list - working allows to create new products, these are also created in HAOS Master data - I can do everything here

Environment:

  • iOS app v1.2.1
  • Grocy on HAOS from HACS v3.1.0
  • Addon Grocy from HAOS v0.15.0

All of them have default settings, not played with ssl yet, no changed ports. If so I can send you logs :) anyways thank you for this update!

Disabling some of the extensions can make this bug appear, make sure every extension is enabled in the config.yaml file of the addon

Lemonadel commented 3 years ago

I was about to write about the same issue. Well that’s weird but it was caused by batteries and tasks set to 'false' in this yaml config. So setting them back to 'true' fixed this. Thank you!