Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed login with --cred got hang #350

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 17 additions & 35 deletions safaribooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
API_ORIGIN_URL = "https://" + API_ORIGIN_HOST
PROFILE_URL = SAFARI_BASE_URL + "/profile/"

# Basic token, used to perform the login, this is hardcoded in IOS app
BASIC_TOKEN = 'Basic MDUyMDc5OjAwYTYzYzA4ZTlkMjQwYjZmNGYxNGI5M2ExMzVkYTIyN2U4YjlkYTk5MTAzZGIzOGM0YjRlYjRj'

# DEBUG
USE_PROXY = False
PROXIES = {"https": "https://127.0.0.1:8080"}
Expand Down Expand Up @@ -228,6 +231,9 @@ class SafariBooks:
LOGIN_URL = ORLY_BASE_URL + "/member/auth/login/"
LOGIN_ENTRY_URL = SAFARI_BASE_URL + "/login/unified/?next=/home/"

API_LOGIN_URL = API_ORIGIN_URL + "/api/v1/auth/login/"
API_LOGIN_LOOKUP_URL = API_ORIGIN_URL + "/api/m/v2/auth/lookup/"

API_TEMPLATE = SAFARI_BASE_URL + "/api/v1/book/{0}/"

BASE_01_HTML = "<!DOCTYPE html>\n" \
Expand Down Expand Up @@ -462,53 +468,29 @@ def parse_cred(cred):
return new_cred

def do_login(self, email, password):
response = self.requests_provider(self.LOGIN_ENTRY_URL)
if response == 0:
self.display.exit("Login: unable to reach Safari Books Online. Try again...")

next_parameter = None
try:
next_parameter = parse_qs(urlparse(response.request.url).query)["next"][0]
response = self.requests_provider(self.API_LOGIN_LOOKUP_URL, is_post=True, json={"email": email})
lookup_response_body = response.json()

except (AttributeError, ValueError, IndexError):
self.display.exit("Login: unable to complete login on Safari Books Online. Try again...")

redirect_uri = API_ORIGIN_URL + quote_plus(next_parameter)
if not lookup_response_body.get('password_login_allowed', False):
self.display.exit("Login: unable to reach Safari Books Online. Try again...")

response = self.requests_provider(
self.LOGIN_URL,
self.API_LOGIN_URL,
is_post=True,
json={
"email": email,
"password": password,
"redirect_uri": redirect_uri
},
headers={
"Authorization": BASIC_TOKEN
},
perform_redirect=False
)

if response == 0:
self.display.exit("Login: unable to perform auth to Safari Books Online.\n Try again...")
login_response_body = response.json()

if response.status_code != 200: # TODO To be reviewed
try:
error_page = html.fromstring(response.text)
errors_message = error_page.xpath("//ul[@class='errorlist']//li/text()")
recaptcha = error_page.xpath("//div[@class='g-recaptcha']")
messages = ([" `%s`" % error for error in errors_message
if "password" in error or "email" in error] if len(errors_message) else []) + \
([" `ReCaptcha required (wait or do logout from the website).`"] if len(
recaptcha) else [])
self.display.exit(
"Login: unable to perform auth login to Safari Books Online.\n" + self.display.SH_YELLOW +
"[*]" + self.display.SH_DEFAULT + " Details:\n" + "%s" % "\n".join(
messages if len(messages) else [" Unexpected error!"])
)
except (html.etree.ParseError, html.etree.ParserError) as parsing_error:
self.display.error(parsing_error)
self.display.exit(
"Login: your login went wrong and it encountered in an error"
" trying to parse the login details of Safari Books Online. Try again..."
)
if not login_response_body.get('logged_in',False):
self.display.exit("Login: unable to perform auth to Safari Books Online.\n Try again...")

self.jwt = response.json() # TODO: save JWT Tokens and use the refresh_token to restore user session
response = self.requests_provider(self.jwt["redirect_uri"])
Expand Down