petergardfjall / garminexport

Garmin Connect activity exporter and backup tool
Apache License 2.0
500 stars 85 forks source link

402 Error Downloading Files #106

Closed app4g closed 10 months ago

app4g commented 11 months ago

It was working 8hours ago.. Went to sleep and then this happens today. Auth is successful, Upload/Download is failing

this is using the package from https://github.com/petergardfjall/garminexport/issues/103

pip uninstall garmin-backup
pip install "git+https://github.com/petergardfjall/garminexport.git@browser-tls-fingerprint-bypass#egg=garminexport[impersonate_browser]"

➜ ~ garmin-get-activity --password XXXX --log-level DEBUG XXXX@gmail.com 19323150075 fit

2023-10-20 07:06:44,894 [INFO] using 'curl_cffi' to create HTTP sessions that impersonate web browser 'chrome110' ...
2023-10-20 07:06:44,897 [INFO] authenticating user ...
2023-10-20 07:06:44,897 [INFO] passing login credentials ...
2023-10-20 07:06:46,011 [DEBUG] got auth response 200: {"serviceURL":"https://connect.garmin.com/modern/","serviceTicketId":"ST-2177081-oRNrJ3GMwsQpPL7b2XXX-sso","responseStatus":{"type":"SUCCESSFUL","message":"","httpStatus":"OK"},"customerMfaInfo":null,"consentTypeList":null}
2023-10-20 07:06:46,011 [DEBUG] auth ticket url: 'https://connect.garmin.com/modern?ticket=ST-2177081-oRNrJ3GMwsQpPL7b2XXX-sso'
2023-10-20 07:06:48,844 [INFO] claiming auth ticket https://connect.garmin.com/modern?ticket=ST-2177081-oRNrJ3GMwsQpPL7b2XXX-sso ...
2023-10-20 07:06:50,373 [INFO] fetching activity 19323150075 ...
2023-10-20 07:06:50,577 [ERROR] failed to fetch json summary for activity 19323150075: 402

2023-10-20 07:06:50,579 [ERROR] failed with exception: failed to fetch json summary for activity 19323150075: 402

Traceback (most recent call last):
  File "/Users/user/.pyenv/versions/3.11.5/bin/garmin-get-activity", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/Users/user/.pyenv/versions/3.11.5/lib/python3.11/site-packages/garminexport/cli/get_activity.py", line 68, in main
    summary = client.get_activity_summary(args.activity)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/.pyenv/versions/3.11.5/lib/python3.11/site-packages/garminexport/garminclient.py", line 46, in check_session
    return client_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/user/.pyenv/versions/3.11.5/lib/python3.11/site-packages/garminexport/garminclient.py", line 268, in get_activity_summary
    raise Exception(u"failed to fetch json summary for activity {}: {}\n{}".format(
Exception: failed to fetch json summary for activity 19323150075: 402

the endpoint - https://connect.garmin.com/proxy/upload-service/upload/.fit is getting blocked/something. I've also tried https://connect.garmin.com/upload-service/upload/.fit which also does not work.

this works - https://connect.garmin.com/modern/proxy/device-service/deviceservice/mylastused and https://connect.garmin.com/modern/proxy/activitylist-service/activities/search/activities also works to return the list of activities. Just unable to upload/download any fit files

app4g commented 11 months ago

8hrs later and https://connect.garmin.com/modern/proxy/device-service/deviceservice/mylastused as well as https://connect.garmin.com/modern/proxy/activitylist-service/activities/search/activities cannot be access anymore. Both of these were working yesterday and today it is giving 402 error

GameDr04 commented 11 months ago

I'll post the same thing I posted in another issue raised (as I now realize it's more relevant, here):

Things are breaking because the endpoints for • weigh-ins • activities (workouts) • daily stuff (watch measurements) have all changed. They used to be proxy URLs, but they're all uniform now, and they all require the bearer token.

[WORKOUTS] formerly: https://connect.garmin.com/modern/proxy/userprofile-service/userprofile/personal-information/weightWithOutbound/filterByDay?from=x&until=y currently: https://connect.garmin.com/activitylist-service/activities/list/USERNAME?startTimestampLocal=2023-10-20T00:00:00.00&endTimestampLocal=2023-10-20T23:59:59.999

[WEIGH-INS] formerly: https://connect.garmin.com/modern/proxy/userprofile-service/userprofile/personal-information/weightWithOutbound/filterByDay?from=x&until=y currently: https://connect.garmin.com/weight-service/weight/daterangesnapshot?startDate=2023-09-19&endDate=2023-10-20

[DAILIES] formerly: https://connect.garmin.com/modern/proxy/usersummary-service/usersummary/daily/USERNAME?calendarDate= currently: https://connect.garmin.com/usersummary-service/usersummary/daily/USERNAME?calendarDate=2023-10-20

These changed today (for me anyway, 20-Oct-2023) and are no longer proxies to their internal API. They were the last three (if memory serves) that could be accessed without a bearer token. Now everything hits the same endpoint.

I don't have a pull request but with this information, somebody might be able to put one together more quickly than I can.

e7andy commented 11 months ago

After I changed to the new URL I get "404 Not found" instead of 402. I then added the header 'di-backend': 'connectapi.garmin.com' which changed the response to "403 forbidden".

Other headers that I believe have been added are 'baggage' and 'sentry-trace'.

app4g commented 11 months ago

@GameDr04 How were you able to determine these new endpoints? I was only looking at the javascript console and didn't see these.

GameDr04 commented 11 months ago

@app4g That's how I found them.

I went to my Connect dashboard and I searched through the many requests until I found the URLs that returned the same data as the old ones. I searched the responses for "Elliptical" to find workouts, knowing I had just done one such workout. "mass" for weigh-ins. "bmrKilocalories" for dailies/watch logs.

If you filter your Network console by • activitylist-serviceweight-service • and usersummary-service, you should see the new endpoints.

It should also be noted that the three URLs I listed return similar payloads, but the structures are a bit different. For instance, the workouts (or "activities") payload used to return a bare array, but now all workouts are stored under the activityList key. Weigh-in data also used to be a bare array, but it is now stored under the dateWeightList key.

ALSO, some information has moved from one structure to another, or has been renamed. And there are new keys in daily reports such as wellnessActiveKilocalories and wellnessKilocalories that seem to be mirrors of older keys. My guess is a deprecation is on the horizon.

GameDr04 commented 11 months ago

In response to what @e7andy said: the three endpoints whose URLs changed didn't used to require the Authorization header (which contains the Bearer token), but they do now. Without it, 403s abound.

I also think that the X-App-Ver header is required now, but don't quote me on that.

app4g commented 11 months ago

Looks like from what I can tell, they all have Authorization: Bearer now. I am not sure if they had it yday tho. I did take a screenshot of the gear-service which was working 2days ago. (notice the auth bearer is already there, but was working)

Screenshot 2023-10-22 at 6 54 23 PM
SimonBaars commented 11 months ago

@app4g Could you try it with the https://github.com/petergardfjall/garminexport/pull/104 branch? I think the Garth approach should still work, since it migrated the endpoints.

app4g commented 11 months ago

@SimonBaars yes.. The Garth approach still works. Im using the cyberjunky/garminconnect right now.

petergardfjall commented 11 months ago

Would anyone mind trying running through the branch in https://github.com/petergardfjall/garminexport/pull/105? That seems to do the trick for me after adding 9fcde6b7cde4a3ab4af80578c1a8cb6dd3f88950.

petergardfjall commented 10 months ago

I just released garminexport 0.5.0, which I believe should resolve this issue. It is strongly adviced to install with the impersonate_browser extra: pip install "garminexport[impersonate_browser]".