Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

having issues logging in #199

Closed
chrisdrackett opened this issue Dec 10, 2023 · 25 comments · Fixed by #201
Closed

having issues logging in #199

chrisdrackett opened this issue Dec 10, 2023 · 25 comments · Fixed by #201

Comments

@chrisdrackett
Copy link

Getting the following in HASS that I assume is a surepy issue (well, a sure petcare issue really I would guess)

2023-12-10 13:30:26.544 ERROR (MainThread) [surepy.client] 🐾 �[38;2;255;26;102m·�[0m GET app.api.surehub.io/api/me/start: 401 | <ClientResponse(https://app.api.surehub.io/api/me/start) [401 Unauthorized]>
2023-12-10 13:30:28.024 DEBUG (MainThread) [surepy.client] 🐾 �[38;2;0;255;0m·�[0m GET app.api.surehub.io/api/me/start | 6
2023-12-10 13:30:28.025 DEBUG (MainThread) [homeassistant.components.surepetcare] Finished fetching surepetcare data in 1.623 seconds (success: False)
2023-12-10 13:30:28.025 WARNING (MainThread) [homeassistant.config_entries] Config entry 'Sure Petcare' for surepetcare integration could not authenticate: Invalid username/password

@chrisdrackett
Copy link
Author

looks like this URL might have changed to app-api.blue.production.surehub.io

@chrisdrackett
Copy link
Author

ok, I was able to login using the following URL: https://app-api.blue.production.surehub.io/api/auth/login and also use https://app-api.blue.production.surehub.io/api/device successfully so I think this is a pretty easy change. I'll submit a PR

@ivo-toby
Copy link

Is there anyway to force this change in hassos (eg; where can I find the integration)?
I'm about to go on vacation and I really want Home-assistant to control the catflap instead of the Sure App

@Hoefnix
Copy link

Hoefnix commented Dec 13, 2023

changing just the urls don’t do the trick, at least for me. Gives me a415 error as result.

{'type': 'https://tools.ietf.org/html/rfc7231#section-6.5.13', 'title': 'Unsupported Media Type', 'status': 415, 'traceId
': '00-f9df16e657295223a3f7043349f5b64f-2199f73a6430e892-00'}

@DevinRouth
Copy link

Same for me—updating the URL's on the client.py and const.py files still results in the same errors (surepy.exceptions.SurePetcareError: ERROR (UN)LOCKING DEVICE - PLEASE CHECK IMMEDIATELY! or 401 errors).

Trying both the URL suggested in this issue (app-api.blue.production.surehub.io) as well as the URL suggested here (https://app-api.production.surehub.io/api/start) both continue to throw errors.

@rjclocks
Copy link

rjclocks commented Dec 13, 2023

I turned on some of the logging info and found that the login request is returning an error:
[415 Unsupported Media Type]
This is consistent across all of the URLs suggested above.

Here is the detail I see from the debug logger:

DEBUG:asyncio:Using proactor: IocpProactor

DEBUG:surepy.client:initialization completed | vars(): 
{'self': <surepy.client.SureAPIClient object at 0x00000>, 
'email': 'AccountEmail', 
'password': 'AccountPassword', 
'auth_token': None, 
'api_timeout': 45, 
'session': None, 
'surepy_version': '0.8.0', 
'token': None}

DEBUG:surepy:initialization completed | vars(): 
{'self': <surepy.Surepy object at 0x00000>, 
'email': 'AccountEmail', 
'password': 'AccountPassword', 
'auth_token': None, 
'api_timeout': 45, 
'session': None}

DEBUG:surepy.client:

DEBUG:surepy.client:🐾 GET call to: https://app.api.surehub.io/api/me/start

DEBUG:surepy.client:Response from https://app.api.surehub.io/api/auth/login: 
<ClientResponse(https://app.api.surehub.io/api/auth/login) [415 Unsupported Media Type]>
<CIMultiDictProxy('Date': 'Wed, 13 Dec 2023 16:10:35 GMT',
 'Content-Type': 'application/json; charset=utf-8', 
 'Transfer-Encoding': 'chunked', 
 'Connection': 'keep-alive', 
 'Server': 'nginx', 
 'Access-Control-Allow-Origin': '*', 
 'Strict-Transport-Security': 'max-age=31536000; includeSubdomains; preload', 
 'X-Frame-Options': 'DENY', 
 'X-Content-Type-Options': 'nosniff', 
 'X-XSS-Protection': '1; mode=block')>

Following all this, I get the usual python exception error

@chrisdrackett
Copy link
Author

So it looks like there are a couple things going on here that I missed:

  1. sure looks to be using blue/green deployment. This isn't something I'm super familiar with, so I'm not sure the best way to have this library deal with it.
  2. The API is expecting application/json requests. I missed this as I was using postman for my testing and this is the encoding I defaulted to.

@blair287
Copy link

blair287 commented Dec 13, 2023

Think this is the end of the road? Or can it be fixed @benleb ?

@cs12ag
Copy link

cs12ag commented Dec 13, 2023

It can definitely be fixed - I'm not sure where benleb is or what he's up to right now though. This stuff is open-source though, so others can suggest changes via PRs.

SurePetcare have always taken the line that their API isn't public, so it's going to be challenging to work out which end-point should be used. From what I've seen so far, that's the only stumbling block. The rest can probably be reverse-engineered.

@chrisdrackett
Copy link
Author

might just be a matter of trying to hit blue first, and if it fails, try green ¯_(ツ)_/¯

@flyize
Copy link

flyize commented Dec 13, 2023

There has to be some sort of DNS redirection to green or blue. Probably something they're doing with Route53. I don't see any other domain that's obvious in the replies though.

@Hoefnix
Copy link

Hoefnix commented Dec 13, 2023

What does this mean?

HTTPSConn
ectionPool(host='app-api.green.production.surehub.io', port=443): Max retries exceeded with
url: /api/auth/login (Caused by SSLError(CertificateError("hostname 'app-api.green.product
ion.surehub.io' doesn't match either of 'blue.production.surehub.io', '.blue.production.su
rehub.io', 'surehub.io', '
.production.surehub.io', '.surehub.io', 'surepetcare.io', '.ap
i.surehub.io', '*.surepetcare.io'")))

@flyize
Copy link

flyize commented Dec 14, 2023

BTW, looks like blue/green isn't necessary anyway. I get a full response from this command (on Windows, hence the caret):

curl -v https://app-api.production.surehub.io/api/me/start ^
-H "Authorization: Bearer ***yourtokenhere**"

@benleb
Copy link
Owner

benleb commented Dec 14, 2023

sorry guys, will have a look at this at the weekend... but from first look here, its a problem on their side where a workaround has to be built?!

About API is expecting application/json requests... the accept header is already set and when also adding content-type I get a 400 bad request :D will dig deeper at the weekend :)

@cs12ag
Copy link

cs12ag commented Dec 14, 2023

@flyize I spent about 30 seconds trawling through JS on the surepetcare.io website to see if I could determine which API end-point was used, but the code is massively obfuscated so I gave up on that immediately.

I'm sticking with my theory that the end-point without the colours in it is the primary end-point, and some kind of load-balancing will redirect requests to blue and green end-points as required. I also think that the swagger docs on all three end-points aren't necessarily 100%; from my testing earlier on this week, the primary end-point looked like it was the only one that can issue auth tokens.

I'm also not ruling out surepetcare taking a buggy/unfinished end-point live. This isn't a below-the-belt blow targeted at surepetcare themselves; we've all pushed stuff to production that may have resulted in bugs revealing themselves. ;)

@benleb
Copy link
Owner

benleb commented Dec 14, 2023

@flyize I spent about 30 seconds trawling through JS on the surepetcare.io website to see if I could determine which API end-point was used, but the code is massively obfuscated so I gave up on that immediately.

probably just a typo, but the (for us) relevant page is https://surehub.io (js is also obfuscated here)

@AlexC
Copy link

AlexC commented Dec 14, 2023

I've just taken a look at the HTTP traffic through a proxy, and the endpoint to use is https://app-api.production.surehub.io/api/. Anything related to blue/green would be a blue/green deployment of their API and not endpoints that should be used directly (normally).

For the issue that I've been facing (unable to set Pet location in Home Assistant, see home-assistant/core#105730), here is the request that the application makes to do the same:

METHOD: POST
URL: https://app-api.production.surehub.io/api/pet/376871/position
HEADERS
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Authorization: Bearer ....
Connection: keep-alive
Content-Length: 41
Content-Type: application/json
Host: app-api.production.surehub.io
Origin: http://localhost
Referer: http://localhost/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Linux; Android 14; sdk_gphone64_x86_64 Build/UE1A.230829.036; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.136 Mobile Safari/537.36
X-App-Version: 3.3.4
X-Device-Id: aae2836efd73a6d1
X-Requested-With: com.sureflap.surepetcare

So we can see https://app-api.production.surehub.io/api/ vs https://app.api.surehub.io/ (this library). However, that may not be the full underlying issue here as the old URL still works.

The issue that I have been facing with Home Assistant is that I'm getting back a HTTP 415 response, which indicates an issue with the Content-Type header. Well, looking at the code for set_pet_location the Content-Type header is never set, which is the problem.

Here's an example using no Content-Type and the old endpoint:

curl --location 'https://app.api.surehub.io/api/pet/376871/position' \
--header 'Authorization: Bearer ...' \
--data '{
  "where": 2,
  "since": "2023-12-14 16:07:38"
}'

{"type":"https://tools.ietf.org/html/rfc7231#section-6.5.13","title":"Unsupported Media Type","status":415,"traceId":"00-25b716e8dfdafaa45e99b517096c7646-461a978e865db0b2-00"}

And with the correct Content-Type:

curl --location 'https://app.api.surehub.io/api/pet/376871/position' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ...' \
--data '{
  "where": 2,
  "since": "2023-12-14 16:07:38"
}'

{"data":{"id":3024813240,"pet_id":376871,"tag_id":409270,"user_id":1234,"where":2,"since":"2023-12-14T16:07:38+00:00"}}

As you can see, it works just fine (even with the assumed old URL). I can work on a little PR for this to get it fixed up if you like?

@AlexC
Copy link

AlexC commented Dec 14, 2023

@benleb I'm unfamiliar with what the older API looked like, but from what I can see it did not expect a JSON payload before, is that correct? If so, the issue here appears to be that the newer version of the Surepet API speaks JSON, and should be rather trivial to use json instead of data kwarg in such calls:

raw_response: aiohttp.ClientResponse = await session.post(
                url=AUTH_RESOURCE, json=authentication_data, headers=self._generate_headers()
            )

@benleb
Copy link
Owner

benleb commented Dec 14, 2023

ah nice @AlexC - can confirm that works for me too! 🎉 👍
(btw, just adding the content-type header and sending data leads to the 400er error I got before -_-)

and what the API really expects or expected... we actually never really knew :D We never got in good contact with sure petcare (we think they dont want to due to some reason :/) and just "reverse engineered" the calls from the app and so on... afaik the headers initially were a copy of what the app sent, but that was years ago...

and about a MR, sure :) 👍 if nobody does it until the weekend, I will :) 👍

@benleb
Copy link
Owner

benleb commented Dec 14, 2023

ah there already is one :D #201 - from sure petcare itself <3 thanks!

but content-type header is missing in that one

@AlexC
Copy link

AlexC commented Dec 14, 2023

@benleb Yeah, I wasn't aware that the Python lib was not sending a JSON payload, so just setting the header to application/json would not be the only fix as the payload would also need to be JSON instead of formdata.

I did receive a notification/message from the official Surepet application the other day, saying that I must update the application to the latest otherwise it will stop working. That ties into the failures that we're seeing here now, so I can only assume they've made some breaking changes to their API (so that it now only speaks JSON, most likely)

The linked PR looks good to me, as the json kwarg would also add in the Content-Type: application/json header so no further changes needed there

@rjclocks
Copy link

I know you have closed this, but I also had to initialise the json object to get it to work (shown below).

async def call(
    self,
    method: str,
    resource: str,
    data: dict[str, Any] | None = None,
    json: dict[str, Any] | None = None,
    second_try: bool = False,
    **_: Any,
) -> dict[str, Any] | None:

@chrisdrackett
Copy link
Author

Just a heads up this still isn't working for me either, I'm still getting a 401:

2023-12-27 08:47:12.514 ERROR (MainThread) [surepy.client] 🐾 �[38;2;255;26;102m·�[0m GET app.api.surehub.io/api/me/start: 401 | <ClientResponse(https://app.api.surehub.io/api/me/start) [401 Unauthorized]>

@rjclocks
Copy link

@chrisdrackett - I would double check that your credentials work correctly on the main Sure Petcare app webpage.
Since the update, all my issues with login have been corrected.

@chrisannen
Copy link

chrisannen commented Dec 27, 2023

@chrisdrackett

I had the same problem. Delete the integration on HA and reinstall it. After that it should work.

But don't forget to update to 2023.12.4 first!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.