Skip to content

Instantly share code, notes, and snippets.

@Terbau
Last active March 5, 2024 16:06
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Terbau/9a07849fb30c0232af730265c327e27c to your computer and use it in GitHub Desktop.
Save Terbau/9a07849fb30c0232af730265c327e27c to your computer and use it in GitHub Desktop.
(Partially outdated) epic games authflow
import requests
# Constants. These should not be tampered with.
base = "https://www.epicgames.com"
base_public_service = "https://account-public-service-prod03.ol.epicgames.com"
launcher_token = "MzQ0NmNkNzI2OTRjNGE0NDg1ZDgxYjc3YWRiYjIxNDE6OTIwOWQ0YTVlMjVhNDU3ZmI5YjA3NDg5ZDMxM2I0MWE="
fortnite_token = "ZWM2ODRiOGM2ODdmNDc5ZmFkZWEzY2IyYWQ4M2Y1YzY6ZTFmMzFjMjExZjI4NDEzMTg2MjYyZDM3YTEzZmM4NGQ="
# Fill out.
email = ""
password = ""
two_factor_code = "" # Leave empty if you want to take an input from the console.
def authenticate(session):
# Request to fetch all cookies needed. With the request module all the
# cookies are automatically stored in the session cookie jar.
session.get(f"{base}/id/api/csrf")
res = session.get(
f"{base}/id/api/reputation",
headers={
'x-xsrf-token': session.cookies.get("XSRF-TOKEN")
},
cookies=session.cookies
)
if res.json()['verdict'] != 'allow':
# If captcha is enforced, it means that you won't be able to log
# to the account on the same ip for a while or on the account
# in general. It is not known exactly what causes this to happen
# but we know in general that it happens when you try to log in
# too many times (often regardless of which accounts). Theres no
# real good workarounds but there is other ways to log in
# like using device auth. This however is a little more complicated
# and does not fit in this simple example.
raise RuntimeError('Captcha was required for this login')
# Attempt to login with email and password.
res = session.post(
f"{base}/id/api/login",
headers={
"x-xsrf-token": session.cookies.get("XSRF-TOKEN")
},
data={
"email": email,
"password": password,
"rememberMe": False,
"captcha": ""
},
cookies=session.cookies
)
# is only true if an error occured
if res.status_code >= 400:
data = res.json()
error = data['errorCode']
if error == 'errors.com.epicgames.account.invalid_account_credentials':
raise ValueError('Invalid credentials')
if error == 'errors.com.epicgames.common.two_factor_authentication.required':
# Since the user we are trying to log in as requires two factor authentication,
# we have to fetch a new xsrf token and use that to authenticate with mfa and
# for the rest of the requests.
session.get(f"{base}/id/api/csrf")
res = session.post(
f"{base}/id/api/login/mfa",
headers={
"x-xsrf-token": session.cookies.get("XSRF-TOKEN")
},
data={
"code": two_factor_code or input("Please enter the 2fa code: "),
"method": "authenticator",
"rememberDevice": False # set to True if you want the device to be remembered
},
cookies=session.cookies
)
if res.status_code >= 400:
mfa_data = res.json()
mfa_error = mfa_data['errorCode']
errors = (
'errors.com.epicgames.accountportal.mfa_code_invalid', # wrong code passed
'errors.com.epicgames.accountportal.validation' # invalid code passed (e.g. wrong amount of characters)
)
if mfa_error in errors:
raise ValueError('Invalid code passed')
# We need new csrf cookies again
session.get(f"{base}/id/api/csrf")
# Fetch exchange code.
res = session.post(
f"{base}/id/api/exchange/generate",
headers={
"x-xsrf-token": session.cookies.get("XSRF-TOKEN")
},
cookies=session.cookies
)
exchange_code = res.json()["code"]
# Exchange the code to fetch the launcher access token.
res = session.post(
f"{base_public_service}/account/api/oauth/token",
headers={
"Authorization": f"basic {launcher_token}"
},
data={
"grant_type": "exchange_code",
"exchange_code": exchange_code,
"token_type": "eg1"
}
)
launcher_access_token = res.json()["access_token"]
# The following code will use the launcher access token to retrieve
# a fortnite access token. If you don't require fortnite permissions
# you can cut out the part below.
res = session.get(
f"{base_public_service}/account/api/oauth/exchange",
headers={
"Authorization": f"Bearer {launcher_access_token}"
}
)
exchange_code = res.json()["code"]
res = session.post(
f"{base_public_service}/account/api/oauth/token",
headers={
"Authorization": f"basic {fortnite_token}"
},
data={
"grant_type": "exchange_code",
"token_type": "eg1",
"exchange_code": exchange_code
}
)
# NOTE: Tokens expires after eight hours.
fortnite_access_token = res.json()["access_token"]
print(fortnite_access_token)
with requests.Session() as session:
authenticate(session)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment