node-toogoodtogo-watcher: v2/loginByEmail endpoint doesn't seem to work anymore

Hi. As per the title:

POST https://apptoogoodtogo.com/api/auth/v2/loginByEmail
{
    "device_type": "UNKNOWN",
    "email": "Email of your TooGoodToGo account.",
    "password": "Password of your TooGoodToGo account."
}
HTTPError: Response code 403 (Forbidden)
    at Request.<anonymous> (/home/node/app/node_modules/got/dist/source/as-promise/index.js:117:42)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)

From my sniffing session, the endpoint has been replaced by v3/authByEmail (not loginByEmail!) which doesn’t use password anymore (even though the app asks for it), but it requires the user to click a link from the verification email (or input the code provided in the app).

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 15 (2 by maintainers)

Most upvoted comments

well, seems I need to tell wifey there will be no more cheap sushi for her 🤕

Would love to see some full walkthrough for this! Might need to fetch the mail programmatically I guess…

It’s been day 2. I think she is starting to notice the empty fridge. Im tooscaredtotell.

Thanks for helping this getting up again. If I can assist in any way.

tooscaredtotell

took a few seconds, but hit right in the laugh box


As time is short, I was able to have a little more play an that one. A few things I found:

They use datadome as bot protection. It is a SaaS solution to prevent people like us to do this like we do. And they are the reason for those captcha-delivery.com stuff.

(If there is any toogoodtogo employee here: pls don’t sue me, we do this for fun and to make our wifes happy and not to hurt anybody. We even pay like regular customers. Don’t ban/sue us pls 🥺 .)

Trying to get fav pulled with the new token always hit me with those captcha requests. While looking at the traffic I saw that the app passes always place some cookie in the header, with I ignored at first.
But, when resuing the cookie from the successful api/auth/v3/authByRequestPollingId post, I got a perfect response!

With that said, I am not sure how their protection works in detail. I tried aggressively to fetch 100 times and now ran against the captcha even when trying to login freshly. App also enforced me to click on traffic lights…

Proof:

image

I think we now have all information needed to fix this thing. As I still have no time and effort to learn node-js, I might jump over to the python one and try to get it working.

Okay, had some little play with mitmproxy:

image

From what I can tell:

  1. the First request goes to https://apptoogoodtogo.com/api/auth/v3/authByEmail and is responded with some polling_id.
  2. Next responses go towards https://apptoogoodtogo.com/api/auth/v3/authByRequestPollingId containing (besides more) the request_polling_id.
  3. as long as the link is not clicked (tried on my workstation) the request is responded with 202
  4. after the link has been clicked it is responded with 200 and contains access token and a access_token_ttl_seconds of 172800s / 2days.

So, throwing that knowledge against some jupyter-notebook (sorry nodejs guys):

image. Note: /authByEmail quickly blocks with 429 too many requests, take care!

Never took a deeper dive, but i guess the gained access_token is what we need to be happy.

So a version that requires the user to open his mail and hit the button should not be that big issue I guess?

The first approach I would try would be to mimic the approach from the app as much as possible.

  1. When the program is started and no session exist yet, start the login procedure by calling the API.
  2. The program starts polling auth/v3/authByRequestPollingId
  3. The API sends the user an email.
  4. The user clicks the link in the email.
  5. The program receives the session and continues.

Things like automating accessing emails and scraping a CSRF token from a HTML form can be done if necessary, but I would avoid them, if possible.

Funny enough, but just adding "accept-encoding": "gzip" after this line fixed the issue: https://github.com/marklagendijk/node-toogoodtogo-watcher/blob/master/lib/api.js#L10! 😆

Final result:

headers: _.defaults(config.get("api.headers"), {
    "Content-Type": "application/json",
    Accept: "application/json",
    "Accept-Language": "en-US",
   "accept-encoding": "gzip"
  }),

That is weird, I don’t have this kind of errors. I have 403 but looks like I can login successfully with email and password (see #113 )

coffee break update:

Using the PIN method is quite similar.

  • After requesting the login email it starts pulling at v3/authByRequestPollingId
  • When the PIN is entered a POST is sent to v3/authByRequestPin with the pin and some more data
  • response is similar to the 200 version of v3/authByRequestPollingId image

Might have a little try to get this into the python version, to have a full walkthrough.

Thinking of using some trash email that allows API usage (e.g. https://temp-mail.org/ ). Adding some forwarding rule towards them fetching the code is candy.