mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-03-18 09:07:30 +00:00
fix(serve): use X-Secret-Key header for REST API auth to match pywidevine
Standardize on X-Secret-Key across all endpoints so RemoteClient, pywidevine CDM, and api-only mode all use the same auth header. Adds lightweight middleware for --api-only mode without pywidevine dep.
This commit is contained in:
@@ -119,13 +119,23 @@ def serve(
|
|||||||
config.serve["playready_devices"] = []
|
config.serve["playready_devices"] = []
|
||||||
config.serve["playready_devices"].extend(list(config.directories.prds.glob("*.prd")))
|
config.serve["playready_devices"].extend(list(config.directories.prds.glob("*.prd")))
|
||||||
|
|
||||||
|
@web.middleware
|
||||||
|
async def api_key_authentication(request: web.Request, handler) -> web.Response:
|
||||||
|
"""Authenticate API requests using X-Secret-Key header."""
|
||||||
|
secret_key = request.headers.get("X-Secret-Key")
|
||||||
|
if not secret_key:
|
||||||
|
return web.json_response({"status": 401, "message": "Secret Key is Empty."}, status=401)
|
||||||
|
if secret_key not in request.app["config"]["users"]:
|
||||||
|
return web.json_response({"status": 401, "message": "Secret Key is Invalid."}, status=401)
|
||||||
|
return await handler(request)
|
||||||
|
|
||||||
if api_only:
|
if api_only:
|
||||||
log.info("Starting REST API server (pywidevine/pyplayready CDM disabled)")
|
log.info("Starting REST API server (pywidevine/pyplayready CDM disabled)")
|
||||||
if no_key:
|
if no_key:
|
||||||
app = web.Application(middlewares=[cors_middleware])
|
app = web.Application(middlewares=[cors_middleware])
|
||||||
app["config"] = {"users": {}}
|
app["config"] = {"users": {}}
|
||||||
else:
|
else:
|
||||||
app = web.Application(middlewares=[cors_middleware, pywidevine_serve.authentication])
|
app = web.Application(middlewares=[cors_middleware, api_key_authentication])
|
||||||
app["config"] = {"users": {api_secret: {"devices": [], "username": "api_user"}}}
|
app["config"] = {"users": {api_secret: {"devices": [], "username": "api_user"}}}
|
||||||
app["debug_api"] = debug_api
|
app["debug_api"] = debug_api
|
||||||
|
|
||||||
|
|||||||
@@ -1367,7 +1367,7 @@ async def session_create_handler(data: Dict[str, Any], request: Optional[web.Req
|
|||||||
from unshackle.core.config import config as app_config
|
from unshackle.core.config import config as app_config
|
||||||
|
|
||||||
session_id = str(uuid_mod.uuid4())
|
session_id = str(uuid_mod.uuid4())
|
||||||
api_key = request.headers.get("X-API-Key", "anonymous") if request else "anonymous"
|
api_key = request.headers.get("X-Secret-Key", "anonymous") if request else "anonymous"
|
||||||
api_key_hash = hashlib.sha256(api_key.encode()).hexdigest()[:12]
|
api_key_hash = hashlib.sha256(api_key.encode()).hexdigest()[:12]
|
||||||
session_cache_tag = f"_sessions/{api_key_hash}/{session_id}/{normalized_service}"
|
session_cache_tag = f"_sessions/{api_key_hash}/{session_id}/{normalized_service}"
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class RemoteClient:
|
|||||||
if self._session is None:
|
if self._session is None:
|
||||||
self._session = requests.Session()
|
self._session = requests.Session()
|
||||||
if self.api_key:
|
if self.api_key:
|
||||||
self._session.headers["X-API-Key"] = self.api_key
|
self._session.headers["X-Secret-Key"] = self.api_key
|
||||||
return self._session
|
return self._session
|
||||||
|
|
||||||
def _request(self, method: str, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
def _request(self, method: str, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
||||||
|
|||||||
Reference in New Issue
Block a user