malmeloo / FindMy.py

🍏 + 🎯 + 🐍 = Everything you need to work with Apple's FindMy network!
http://docs.mikealmel.ooo/FindMy.py/
MIT License
59 stars 7 forks source link

throws meaningful exception for auth failure #38

Open ubertao opened 1 month ago

ubertao commented 1 month ago

I'm getting the following error for calling AppleAccount.fetch_reports():

Traceback (most recent call last):
  File "/opt/./update_findmy_locations.py", line 137, in <module>
    main()
  File "/opt/./update_findmy_locations.py", line 129, in main
    reports = fetch_reports_from_apple(acc, device, fetch_from, fetch_to)
  File "/opt/./update_findmy_locations.py", line 88, in fetch_reports_from_apple
    reports = acc.fetch_reports(list(lookup_keys), fetch_from, fetch_to)
  File "/usr/local/lib/python3.10/site-packages/findmy/reports/account.py", line 1045, in fetch_reports
    return self._evt_loop.run_until_complete(coro)
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.10/site-packages/findmy/reports/account.py", line 641, in fetch_reports
    return await self._reports.fetch_reports(
  File "/usr/local/lib/python3.10/site-packages/findmy/reports/reports.py", line 239, in fetch_reports
    reports.extend(await self._fetch_reports(date_from, date_to, chunk))
  File "/usr/local/lib/python3.10/site-packages/findmy/reports/reports.py", line 260, in _fetch_reports
    data = await self._account.fetch_raw_reports(start_date, end_date, ids)
  File "/usr/local/lib/python3.10/site-packages/findmy/reports/account.py", line 596, in fetch_raw_reports
    resp = r.json()
  File "/usr/local/lib/python3.10/site-packages/findmy/util/http.py", line 48, in json
    return json.loads(self.text())
  File "/usr/local/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/lib/python3.10/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)
ERROR:asyncio:Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7ffffb9c7790>
ERROR:asyncio:Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x7ffffb93e440>, 1058485.242966568)]']
connector: <aiohttp.connector.TCPConnector object at 0x7ffffb9c7760>
ERROR:asyncio:Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7ffffb9c7910>
ERROR:asyncio:Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x7ffffb9c9f00>, 1058486.638551861)]']
connector: <aiohttp.connector.TCPConnector object at 0x7ffffb9c78b0>

The real issue is a 401 error with an empty response from iCloud API. May we have a meaningful exception so my code knows how to handle the re-login?

malmeloo commented 1 month ago

So logging in again fixes the issue? I think this can be avoided by refreshing the mobileme login, which can be done without redoing the account login flow. That means the library should handle it instead of the end user.

ubertao commented 1 month ago

Yes, logging in again will fix the issue.

But for my use case, instead of leaving it to library, I'd rather like to get an exception or error code then handle the re-login myself. That's because I have 2 separate scripts:

  1. update.py - a lambda function running on cloud, invoked periodically and automatically, uses existing account.json to fetch location data
  2. login.py - running locally, invoked by user to generate account.json required by update.py

I can't handle re-login in update.py because it needs to wait for user's 2FA input. If update.py gets an 401 error, it can delete the account.json and send an alert to user, stop there until it gets a new valid account.json.

malmeloo commented 1 month ago

Oh no that shouldn't require doing the 2FA flow, I should've been more clear about that. Essentially, the login flow consists of the following steps:

  1. Login to apple account
  2. (only if required) Do 2FA challenge, go back to step 1
  3. Login to mobileme

Information from that 3rd step is then used to fetch location reports. I think that redoing that 3rd step to obtain new tokens will fix the 401 issue, and it does not require doing the 2FA flow. So my proposed solution is to let the library attempt to do step 3 again if it notices that reauth is required, and raise some kind of UnauthenticatedError if that fails.

ubertao commented 1 month ago

Thanks for the clarification, your solution sounds good.

wes1993 commented 3 weeks ago

Hello, Seems that the library won't works anymore.... for every new location key I have the error below:

WARNING:root:Location report was not decodable. Some payloads have unknown variations leading to this error. Please report this full message at https://github.com/malmeloo/FindMy.py/issues/27. Payload: <Hidden By ME>, Original error: Unsupported elliptic curve point type

The last working report is 06/06/2024