Support passing the Auth token as a url param.
This is required to support ebook downloads which the Kobo device emits without any auth headers. * Also some other small bug fixes discovered during device testing.
This commit is contained in:
parent
0926ae530c
commit
fffa2d5a1b
|
@ -445,7 +445,7 @@ def get_book_cover_with_uuid(book_uuid,
|
||||||
|
|
||||||
def get_book_cover_internal(book,
|
def get_book_cover_internal(book,
|
||||||
use_generic_cover_on_failure):
|
use_generic_cover_on_failure):
|
||||||
if book.has_cover:
|
if book and book.has_cover:
|
||||||
if config.config_use_google_drive:
|
if config.config_use_google_drive:
|
||||||
try:
|
try:
|
||||||
if not gd.is_gdrive_ready():
|
if not gd.is_gdrive_ready():
|
||||||
|
|
17
cps/kobo.py
17
cps/kobo.py
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import base64
|
||||||
import copy
|
import copy
|
||||||
import uuid
|
import uuid
|
||||||
import os
|
import os
|
||||||
|
@ -25,8 +26,6 @@ kobo_auth.disable_failed_auth_redirect_for_blueprint(kobo)
|
||||||
|
|
||||||
log = logger.create()
|
log = logger.create()
|
||||||
|
|
||||||
import base64
|
|
||||||
|
|
||||||
|
|
||||||
def b64encode(data):
|
def b64encode(data):
|
||||||
return base64.b64encode(data)
|
return base64.b64encode(data)
|
||||||
|
@ -92,10 +91,12 @@ class SyncToken:
|
||||||
if "." in sync_token_header:
|
if "." in sync_token_header:
|
||||||
return SyncToken(raw_kobo_store_token=sync_token_header)
|
return SyncToken(raw_kobo_store_token=sync_token_header)
|
||||||
|
|
||||||
sync_token_json = json.loads(
|
|
||||||
base64.b64decode(sync_token_header + "=" * (-len(sync_token_header) % 4))
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
|
sync_token_json = json.loads(
|
||||||
|
base64.b64decode(
|
||||||
|
sync_token_header + "=" * (-len(sync_token_header) % 4)
|
||||||
|
)
|
||||||
|
)
|
||||||
validate(sync_token_json, SyncToken.token_schema)
|
validate(sync_token_json, SyncToken.token_schema)
|
||||||
if sync_token_json["version"] < SyncToken.MIN_VERSION:
|
if sync_token_json["version"] < SyncToken.MIN_VERSION:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
@ -217,8 +218,10 @@ def get_metadata__v1(book_uuid):
|
||||||
|
|
||||||
|
|
||||||
def get_download_url_for_book(book):
|
def get_download_url_for_book(book):
|
||||||
return "{url_base}/download/{book_id}/kepub".format(
|
return "{url_base}/download/{book_id}/kepub?{auth_token_param}".format(
|
||||||
url_base=config.config_server_url, book_id=book.id
|
url_base=config.config_server_url,
|
||||||
|
book_id=book.id,
|
||||||
|
auth_token_param=kobo_auth.get_auth_url_param(request),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,8 @@ from werkzeug.security import check_password_hash
|
||||||
from . import logger, ub, lm
|
from . import logger, ub, lm
|
||||||
|
|
||||||
USER_KEY_HEADER = "x-kobo-userkey"
|
USER_KEY_HEADER = "x-kobo-userkey"
|
||||||
|
USER_KEY_URL_PARAM = "kobo_userkey"
|
||||||
|
|
||||||
log = logger.create()
|
log = logger.create()
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +61,7 @@ def disable_failed_auth_redirect_for_blueprint(bp):
|
||||||
|
|
||||||
@lm.request_loader
|
@lm.request_loader
|
||||||
def load_user_from_kobo_request(request):
|
def load_user_from_kobo_request(request):
|
||||||
user_key = request.headers.get(USER_KEY_HEADER)
|
user_key = get_auth_token_from_request(request)
|
||||||
if user_key:
|
if user_key:
|
||||||
for user in (
|
for user in (
|
||||||
ub.session.query(ub.User).filter(ub.User.kobo_user_key_hash != "").all()
|
ub.session.query(ub.User).filter(ub.User.kobo_user_key_hash != "").all()
|
||||||
|
@ -68,3 +70,20 @@ def load_user_from_kobo_request(request):
|
||||||
return user
|
return user
|
||||||
log.info("Received Kobo request without a recognizable UserKey.")
|
log.info("Received Kobo request without a recognizable UserKey.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_auth_token_from_request(request):
|
||||||
|
user_key = request.headers.get(USER_KEY_HEADER)
|
||||||
|
if not user_key:
|
||||||
|
user_key = request.args.get(USER_KEY_URL_PARAM)
|
||||||
|
return user_key
|
||||||
|
|
||||||
|
|
||||||
|
def get_auth_url_param(request):
|
||||||
|
# Some of the API requests emitted by the Kobo device don't set any headers. To
|
||||||
|
# support those calls, authorization on those endpoints can only rely on URL params.
|
||||||
|
# Since the raw UserKey in already leaked in headers, it is probably not *that* much
|
||||||
|
# worse to also leak it over url params.
|
||||||
|
# Ideally however, we should be generating short-lived tokens that grant limited
|
||||||
|
# access instead..
|
||||||
|
return USER_KEY_URL_PARAM + "=" + get_auth_token_from_request(request)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user