[cli/core] Implement newer Epic authentication scheme

Fixes #52
This commit is contained in:
derrod 2020-05-31 02:01:39 +02:00
parent 1531177d8d
commit 3063f02db3
2 changed files with 47 additions and 10 deletions

View file

@ -56,6 +56,7 @@ class LegendaryCLI:
if self.core.login():
logger.info('Stored credentials are still valid, if you wish to switch to a different '
'account, run "legendary auth --delete" and try again.')
return
except ValueError:
pass
except InvalidCredentialsError:
@ -76,21 +77,27 @@ class LegendaryCLI:
logger.error('No EGS login session found, please login normally.')
exit(1)
if not args.auth_code:
exchange_token = ''
if not args.auth_code and not args.session_id:
# unfortunately the captcha stuff makes a complete CLI login flow kinda impossible right now...
print('Please login via the epic web login!')
webbrowser.open(
'https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fexchange'
'https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fredirect'
)
print('If web page did not open automatically, please navigate '
'to https://www.epicgames.com/id/login in your web browser')
print('- In case you opened the link manually; please open https://www.epicgames.com/id/api/exchange '
'in your web browser after you have finished logging in.')
exchange_code = input('Please enter code from JSON response: ')
exchange_token = exchange_code.strip().strip('"')
else:
print('If web page did not open automatically, please manually open the following URL: '
'https://www.epicgames.com/id/login?redirectUrl=https://www.epicgames.com/id/api/redirect')
sid = input('Please enter the "sid" value from the JSON response: ')
sid = sid.strip().strip('"')
exchange_token = self.core.auth_sid(sid)
elif args.session_id:
exchange_token = self.core.auth_sid(args.session_id)
elif args.auth_code:
exchange_token = args.auth_code
if not exchange_token:
logger.fatal('No exchange token, cannot login.')
return
if self.core.auth_code(exchange_token):
logger.info(f'Successfully logged in as "{self.core.lgd.userdata["displayName"]}"')
else:
@ -904,6 +911,8 @@ def main():
help='Import Epic Games Launcher authentication data (logs out of EGL)')
auth_parser.add_argument('--code', dest='auth_code', action='store', metavar='<exchange code>',
help='Use specified exchange code instead of interactive authentication')
auth_parser.add_argument('--sid', dest='session_id', action='store', metavar='<session id>',
help='Use specified session id instead of interactive authentication')
auth_parser.add_argument('--delete', dest='auth_delete', action='store_true',
help='Remove existing authentication (log out)')

View file

@ -12,7 +12,7 @@ from datetime import datetime, timezone
from locale import getdefaultlocale
from multiprocessing import Queue
from random import choice as randchoice
from requests import Request
from requests import Request, session
from requests.exceptions import HTTPError
from typing import List, Dict
from uuid import uuid4
@ -88,6 +88,34 @@ class LegendaryCore:
"""
raise NotImplementedError
def auth_sid(self, sid) -> str:
"""
Handles getting an exchange code from a session id
:param sid: session id
:return: exchange code
"""
s = session()
s.headers.update({
'X-Epic-Event-Action': 'login',
'X-Epic-Event-Category': 'login',
'X-Epic-Strategy-Flags': '',
'X-Requested-With': 'XMLHttpRequest'
})
# get first set of cookies (EPIC_BEARER_TOKEN etc.)
_ = s.get('https://www.epicgames.com/id/api/set-sid', params=dict(sid=sid))
# get XSRF-TOKEN and EPIC_SESSION_AP cookie
_ = s.get('https://www.epicgames.com/id/api/csrf')
# finally, get the exchange code
r = s.post('https://www.epicgames.com/id/api/exchange/generate',
headers={'X-XSRF-TOKEN': s.cookies['XSRF-TOKEN']})
if r.status_code == 200:
return r.json()['code']
else:
self.log.error(f'Getting exchange code failed: {r.json()}')
return ''
def auth_code(self, code) -> bool:
"""
Handles authentication via exchange code (either retrieved manually or automatically)