MixV2 / EpicResearch

Research about Epic Games' non-documented API
341 stars 86 forks source link

Unknown secret for the client named graphqlWebsite #89

Closed woctezuma closed 2 years ago

woctezuma commented 2 years ago

In Auth Clients, the client called graphqlWebsite has an ID, but its secret is unknown.

Unknown secret

1) Does that mean that I can authenticate neither by authorization code, nor using client credentials, because both methods would require a secret?

2) Or can I work directly with the authorization code returned by visiting the following URL?

https://www.epicgames.com/id/api/redirect?clientId=319e1527d0be4457a1067829fc0ad86e&responseType=code

Indeed, I notice that the redirectURL looks like:

https://graphql.epicgames.com/graphql?code=XXX

So it is enticing to use that XXX code along my queries, but I am not sure whether I would get higher permissions by doing so.

3) Otherwise, is there any other client (with known secret) that I could use to get higher permissions to read data from the API with GraphQL? With the few which I have tried, the POST request times out when I submit the access token in the headers like:

import requests

access_token = "MY_TOKEN"

r = requests.post(
    url="https://graphql.epicgames.com/graphql",
    json={"query": "{ Catalog { searchStore(count:3, start: 1617) { paging {total} elements {title} } } }"},
    headers={"Authorization": f'Bearer {access_token}'},
)

whereas this works, but without any higher permission:

import requests

r = requests.post(
    url="https://graphql.epicgames.com/graphql",
    json={"query": "{ Catalog { searchStore(count:3, start: 1617) { paging {total} elements {title} } } }"},
)

At the end of the day, my goal would be to figure out the way the Chinese leaker fetched the upcoming free games: These games were not present in the public database, as can be seen on ScreamDB, so I am very surprised.

Chinese leaker

or the way the French leaker at dealabs.com achieved roughly the same. It has to be a different way, because he has access to less data: he is missing the game to be given away on December 30.

4) Any piece of advice towards this objective?

47PADO47 commented 2 years ago

I don't know if this is what you're searching for, but if you didn't you could take a look here: https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions

woctezuma commented 2 years ago

To answer some of my questions to the best of my current knowledge:

  1. Knowing the client secret is a requirement.
  2. Using the code as a query parameter is likely incorrect. I believe the code is an authorization code (despite the pretty URL), and thus the code is only helpful to ask for an access token (if you know the client secret).
  3. Two points:
    • To avoid the time-out, one needs to ask for a token of type eg1, as shown in derrod/legendary/api/egs.py. These tokens are much longer (length of 1075 base-64 digits instead of 32 hexadecimal digits), and look more secure based on the base64 decoding of some parts of the token: PS256 algorithm, JTI, etc.
    • I have tried all of the clients with a known secret, and none of them have interesting permissions. Actually, using them gives fewer permissions than using the public GraphQL interface without specifying any client ID and secret.
  4. After much poking at the GraphQL API, I am lead to believe that the leakers are contractors for Epic, or have info from insiders, either relatives or friends of theirs.

I don't know if this is what you're searching for, but if you didn't you could take a look here: https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions

Thank you! I know this page, but it is not exhaustive. It is only the visible part of the iceberg database.

For instance, Salt & Sanctuary will be given away later today, but it will appear at your link roughly half an hour before the giveaway. Once its entry appears in the public database (with at least an offer ID and at least an item ID), you will be able to find the game on the official EGS store, at EGData or at ScreamDB. Then you will be able to see the creation date of the database entry, and see that it has been in the invisible part of the database for a while, with an automatic set-up to reveal the entry for today's giveaway, likely planned on December 7 or 8, 2021.

ToutinRoger commented 2 years ago

It doesn't have a secret as it would just authorize with the client id.

woctezuma commented 2 years ago

The thing is I don't even need the client ID to have access to a response for this kind of query, e.g. within Firefox:

https://graphql.epicgames.com/graphql?query={%20Catalog%20{%20searchStore(namespace:%20%22d5241c76f178492ea1540fce45616757%22,%20start:0,%20count:3)%20{%20paging%20{total}%20elements%20{title%20id}%20}%20}%20}

By adding the authorization code as a parameter &code=XXX, I am not sure whether I get access to more info. It looks like the parameter is omitted, and I get the same response, no matter the different queries which I try.


I think the proper way would be to get an Access Token. However, when I do this with clients with known ID and SECRET, then I get an empty response to my query with an error telling me that I don't have permissions to access this data. I believe that this happens because these clients are not the ones which are supposed to have access to the hidden part of the database.

The fact that I get this error message is interesting though, because that means that the GraphQL API properly understood the Authorization header with the OAuth Access Token (of type eg1). When I posted my first message, my Access Tokens were not of type eg1, so I would not get a proper response from the server, and I would get instead a 504 Gateway Timeout error.

ToutinRoger commented 2 years ago

graphqlWebsite never ever had a secret it would just generate a token sorry if i'm not understanding but there is no "hidden part of the database"

ToutinRoger commented 2 years ago

btw &code=XXX won't do anything due to it not being a authorization endpoint, it only works for requests that need it

woctezuma commented 2 years ago

sorry if i'm not understanding but there is no "hidden part of the database"

There is a hidden part of the database. For instance, let us look at "Moving Out", which was given away yesterday.

ScreamDB

---> linked to the item ID: e54d8bf3a451400189159b03231794f7

On Database.EGData.app, one can find 2 entries:


id: "0a8b32256f374cf4998c3ecf44c31db9"
namespace: "f919a1262081444fb28f0fdef68d6b14"
title: "Moving Out" 
productSlug: "moving-out"
urlSlug: "moving-out"
creationDate: "2021-08-10T00:00:34.019Z"
lastModifiedDate: "2021-12-28T14:52:08.774Z"
effectiveDate: "2021-12-28T16:00:00.000Z"
viewableDate: "2021-12-28T16:00:00.000Z" 
---> linked to the item ID: e54d8bf3a451400189159b03231794f7

We can recognize the item ID which is mentioned on ScreamDB: e54d8bf3a451400189159b03231794f7.

We can also see that the entry was:


id: "2cbc0241b606499cb4608ef3711a4bb7"
namespace: "d5241c76f178492ea1540fce45616757"
title: "Moving Out" 
productSlug: "moving-out"
urlSlug: "28mysterygame"
creationDate: "2021-12-07T23:37:01.520Z"
lastModifiedDate: "2021-12-28T14:57:42.495Z"
effectiveDate: "2099-01-01T00:00:00.000Z"
viewableDate: "2021-12-27T15:25:02.000Z" 
---> linked to the item ID: 8341d7c7e4534db7848cc428aa4cbe5a

We can see that the entry is some kind of wrapper for the giveaway:

We can also see that the entry was:


These entries were not created on the day of the giveaway. They must have been in a private part of a database. I believe this could be one way that the leakers get their info early.

For instance, the leaker called billbil-kun at dealabs.com posted his leak on December 9, so roughly 2 days after most entries for giveaways (including the second entry mentioned above) were created. One explanation would be that he had access to the entry created on December 7 and whose urlSlug was set to 28mysterygame. This way, he would know that the game given away on December 28 would be "Moving Out".

Tomorrow, the Tomb Raider trilogy will be given away. A Chinese leaker at bilibili.com knew it on December 25 or earlier. However, the French leaker at dealabs.com did not know it on December 9, and claims he still does not know it today. My guess is that:

If the game given away tomorrow fulfills these conditions, then I will be surprised, and then that is more food for thought. We will see tomorrow. Ultimately, I would like to gain the same permissions to read the complete database as one of these leakers.

ToutinRoger commented 2 years ago

They.. have some kind of source giving them this information, I highly doubt they got permissions to access the information by themselves.

woctezuma commented 2 years ago

You are certainly right.

Indeed, I realize that we know the id of tomorrow's game:

https://graphql.epicgames.com/graphql?query={%20Catalog%20{%20searchStore(namespace:%20%22d5241c76f178492ea1540fce45616757%22,%20start:0,%20count:100)%20{%20paging%20{total}%20elements%20{title%20id}%20}%20}%20}

Tomorrow

So the ID is ce021049651345c9b0e2aa1f295f437f, and there is more info at Database.EGData.app:

id: "ce021049651345c9b0e2aa1f295f437f"
namespace: "d5241c76f178492ea1540fce45616757"
title: "Mystery Game"
productSlug: "[]"
urlSlug: "30mysterygame"
creationDate: "2021-12-07T23:39:09.677Z"
lastModifiedDate: "2021-12-19T16:23:56.660Z"
effectiveDate: "2099-01-01T00:00:00.000Z"
viewableDate: "2021-12-29T15:25:00.000Z" 
---> linked to the item ID: 8341d7c7e4534db7848cc428aa4cbe5a

Therefore, even if we could have accessed this entry before it appeared publicly earlier today, which we could not, then the fields of interest (title, productSlug) would have been obfuscated.

This would explain the lastModifiedDate, which was set to December 28 for the game given away on December 28. In contrast, the lastModifiedDate is currently set to December 19 for the game to be given away tomorrow (on December 30). I would expect the entry to be modified on the day of the giveaway to de-obfuscate the title and productSlug.

In summary, there are two issues with my approach:


Interestingly:

So, if the French leaker could have accessed the database to read the entries for previous giveaways, then he should have been able to read this entry. However, he claimed that he could not read this entry. This points towards another mean of obtaining his pieces of information, most likely through a human being, or third-party companies which work with Epic Games.

As for the Chinese leaker, everything is possible. :)

Jaren8r commented 2 years ago
  1. Otherwise, is there any other client (with known secret) that I could use to get higher permissions to read data from the API with GraphQL? With the few which I have tried, the POST request times out when I submit the access token in the headers like:
import requests

access_token = "MY_TOKEN"

r = requests.post(
    url="https://graphql.epicgames.com/graphql",
    json={"query": "{ Catalog { searchStore(count:3, start: 1617) { paging {total} elements {title} } } }"},
    headers={"Authorization": f'Bearer {access_token}'},
)

If you're trying to authenticate your account to graphql, you need to add a Cookie header to the request with the EPIC_BEARER_TOKEN cookie set to any token that belongs to your account. graphql will internally exchange that token with one belonging to the graphqlWebsiteClient.

woctezuma commented 2 years ago

If you're trying to authenticate your account to graphql, you need to add a Cookie header to the request with the EPIC_BEARER_TOKEN cookie set to any token that belongs to your account. graphql will internally exchange that token with one belonging to the graphqlWebsiteClient.

Thank you! I will try that!

Edit: