Pythe1337N / garmin-connect

Makes it simple to interface with Garmin Connect to get or set any data point.
MIT License
145 stars 59 forks source link

403 Forbidden Response #55

Closed mjpoo closed 1 year ago

mjpoo commented 1 year ago

I've been able to retrieve activities for many months but this morning I get a 403 response when I call GCClient.getActivities.

The body does not contain an array of activities, it contains this error object: { clientMessage: 'Reference Error ID in error logs for further information', errorId: 'e6b09f8b-b515-4307-bd10-2e07c065f515', error: 'WebApplicationException' }

The stacktrace is:

Unhandled rejection StatusCodeError: 403 - "{\"clientMessage\":\"Reference Error ID in error logs for further information\",\"errorId\":\"48588b72-47c0-4ddb-bfc7-7356464e41a7\",\"error\":\"WebApplicationException\"}" at new StatusCodeError (D:\foo\node_modules\request-promise-core\lib\errors.js:32:15) at plumbing.callback (D:\foo\node_modules\request-promise-core\lib\plumbing.js:104:33) at Request.RP$callback [as _callback] (D:\foo\node_modules\request-promise-core\lib\plumbing.js:46:31) at self.callback (D:\foo\node_modules\request\request.js:185:22) at onRequestComplete (D:\foo\node_modules\cloudscraper\index.js:629:3) at onRequestResponse (D:\foo\node_modules\cloudscraper\index.js:207:5) at Request.<anonymous> (D:\foo\node_modules\cloudscraper\index.js:149:7) at Object.onceWrapper (node:events:628:26) at Request.emit (node:events:513:28) at Request.<anonymous> (D:\foo\node_modules\request\request.js:1154:10) at Request.emit (node:events:513:28) at IncomingMessage.<anonymous> (D:\foo\node_modules\request\request.js:1076:12) at Object.onceWrapper (node:events:627:28) at IncomingMessage.emit (node:events:525:35) at endReadableNT (node:internal/streams/readable:1359:12) at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

I ran an npm update and changed to using @garmin/fitsdk (rather than the deprecated @garmin-fit/sdk) but the 403 error still exists.

I have no issues logging into Garmin Connect with the same credentials.

wscourge commented 1 year ago

Same issue

lukasz-mordawski commented 1 year ago

Same here

lukasz-mordawski commented 1 year ago

I tried to debug it for a while. Unforunately I don't know how exactly is GC website working.

First I added few constants to Urls.ts: export const GARMIN_SSO_PORTAL = ${GARMIN_SSO_ORIGIN}/portal export const SIGNIN_URL = ${GARMIN_SSO_PORTAL}/sso/en-US/sign-in?clientId=GarminConnect&service=https%3A%2F%2Fconnect.garmin.com%2Fmodern; export const LOGIN_URL = ${GARMIN_SSO_PORTAL}/api/login?clientId=GarminConnect&locale=en-US&service=https%3A%2F%2Fconnect.garmin.com%2Fmodern%2F;

Then I found is that when I copied this call: 'https://connect.garmin.com/modern/preference/[GUID]' to postman and change url to 'https://connect.garmin.com/modern/currentuser-service/user/info' I successfully got user info data. Using the library is not possible. Maybe some cookie is missing or so.

gooin commented 1 year ago

Garmin has changed the login authentication method, and the previous method is no longer work. I found a great library: Garth (thanks author's hard work), but it is written in Python. I have tried to implement its approach using JavaScript, and it works. I am currently attempting to use its method to modify this library. Once completed, I will submit a merge request.

gooin commented 1 year ago

Here is a initial version where I have rewritten the login method in GarminConnect.ts. In the last step of the login method, I successfully logged in and obtained a token. The next step is to refactor other methods based on this token. Note: the OAUTH_CONSUMER constant in GarminConnect.ts is from Garth's this line Here is my commit: https://github.com/gooin/garmin-connect-cn/commit/5d98de1f57df4b55ddaec6c2cb206a6302375fac

Abasz commented 1 year ago

I have tested this code, and it worked well. I was able to query list of activities, download, edit the activity, etc. Thanks for sharing.

I have one question: I suppose this implementation does not handle MFA right? I can see that the accept-mfa-tokens param is set to true on step 4 but, but I dont see any kind of handler for it.

Also, maintainer of Garth recommends fetching the consumer key/secret rather than hard coding it, I suppose it could change https://github.com/philosowaffle/peloton-to-garmin/issues/524#issuecomment-1741889485

gooin commented 1 year ago

I have one question: I suppose this implementation does not handle MFA right? I can see that the accept-mfa-tokens param is set to true on step 4 but, but I dont see any kind of handler for it.

For a quick test, MFA is ignored, and consumer key is also hard coded , so I need time to polish it :-)

gooin commented 1 year ago

I have added a PR to fix most features, waiting for author review and merge it. See #56. I will publish a temporary package to npm, https://www.npmjs.com/package/@gooin/garmin-connect, hope this can help you. @Abasz

Abasz commented 1 year ago

I have added a PR to fix most features, waiting for author review and merge it. See #56. I will publish a temporary package to npm, https://www.npmjs.com/package/@gooin/garmin-connect, hope this can help you. @Abasz

Thanks! It helped a lot, I have updated both my .NET and TS projects :)

mjpoo commented 1 year ago

Hi @Pythe1337N Do you have any plans to integrate the fixes that @gooin came up with?

Pythe1337N commented 1 year ago

Thanks for all the effort put into this package and sorry for being unresponsive. I'll check #56 and do a release asap.

mjpoo commented 1 year ago

Thanks @Pythe1337N that is very much appreciated.

Pythe1337N commented 1 year ago

Changes from #56 are now merged and released! Enjoy https://www.npmjs.com/package/garmin-connect/v/1.6.0

gooin commented 1 year ago

Changes from #56 are now merged and released! Enjoy https://www.npmjs.com/package/garmin-connect/v/1.6.0

Thanks @Pythe1337N happy to see this merged~

mjpoo commented 1 year ago

Many thanks to everyone who helped fix this. I can confirm it fixed the issue.

pauly commented 1 year ago

~This did completely change the interface though didn't it? I'm no longer sure how to use this.~ I saw the message "getSteps() is not implemented", I thought it was just not implemented yet. also GCClient.get() is gone. Was this intentional? I do appreciate that you made this and updated it, and obviously with no input from me. It was mostly get() that I was using, I will try and work it out and submit a pr, thanks.

loic294 commented 1 year ago

@pauly I opened a PR to fix the "getSteps" https://github.com/Pythe1337N/garmin-connect/pull/58. @Pythe1337N Can you take a look when you have time?

Pythe1337N commented 1 year ago

@pauly general methods seems to be missing, yes. I think you can use GCClient.client.get or copy these lines into a PR: https://github.com/Pythe1337N/garmin-connect/blob/39ae27ee1b883ab29b5257a56852364668bf39e2/src/garmin/GarminConnect.ts#L610

Not sure if the session handling is still required though