feat: add Bearer token auth for federation in AuthMiddleware

This commit is contained in:
Brian Krabach
2026-04-01 10:22:06 -07:00
parent 1f90613030
commit fca55dc49d
2 changed files with 79 additions and 0 deletions
+14
View File
@@ -3,6 +3,8 @@ muxplex authentication — password and signing secret file management.
"""
import base64
import hmac
import logging
import secrets
from pathlib import Path
@@ -11,6 +13,8 @@ from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import JSONResponse, RedirectResponse, Response
_log = logging.getLogger(__name__)
# ---------------------------------------------------------------------------
# Config directory
@@ -164,12 +168,14 @@ class AuthMiddleware(BaseHTTPMiddleware):
secret: str,
ttl_seconds: int,
password: str = "",
federation_key: str = "",
):
super().__init__(app)
self.auth_mode = auth_mode
self.secret = secret
self.ttl_seconds = ttl_seconds
self.password = password
self.federation_key = federation_key
async def dispatch(self, request: Request, call_next) -> Response:
# 1. Localhost bypass — client.host is the socket-level IP and cannot
@@ -192,6 +198,14 @@ class AuthMiddleware(BaseHTTPMiddleware):
if cookie and verify_session_cookie(self.secret, cookie, self.ttl_seconds):
return await call_next(request)
# 4a. Bearer token (server-to-server federation)
auth_header = request.headers.get("authorization", "")
if self.federation_key and auth_header.lower().startswith("bearer "):
token = auth_header[7:]
if hmac.compare_digest(token, self.federation_key):
return await call_next(request)
_log.warning("federation: rejected Bearer from %s", client_host)
# 4b. X-Muxplex-Token header (for cross-origin federation)
token_header = request.headers.get("x-muxplex-token")
if token_header:
+65
View File
@@ -484,3 +484,68 @@ def test_middleware_invalid_token_header_falls_through_to_redirect():
response = client.get("/protected", headers={"X-Muxplex-Token": "bad.token.value"})
# Invalid token: should NOT pass auth, falls through to redirect or 401
assert response.status_code in (307, 401)
# ---------------------------------------------------------------------------
# Bearer token auth (server-to-server federation)
# ---------------------------------------------------------------------------
def _make_federation_app(federation_key: str = "fed-key") -> FastAPI:
"""Create a minimal FastAPI app with AuthMiddleware configured with a federation_key."""
test_app = FastAPI()
test_app.add_middleware(
AuthMiddleware,
auth_mode="password",
secret="test-secret",
ttl_seconds=3600,
password="test-pw",
federation_key=federation_key,
)
@test_app.get("/protected")
async def protected():
return PlainTextResponse("OK")
return test_app
def test_middleware_valid_bearer_token_passes():
"""Non-localhost with valid Bearer token and federation_key configured passes through (200)."""
app = _make_federation_app(federation_key="my-federation-secret")
client = TestClient(app, base_url="http://192.168.1.1")
response = client.get(
"/protected", headers={"Authorization": "Bearer my-federation-secret"}
)
assert response.status_code == 200
assert response.text == "OK"
def test_middleware_invalid_bearer_token_falls_through():
"""Non-localhost with wrong Bearer token falls through to 401 (not accepted)."""
app = _make_federation_app(federation_key="my-federation-secret")
client = TestClient(app, base_url="http://192.168.1.1", follow_redirects=False)
response = client.get(
"/protected",
headers={
"Authorization": "Bearer wrong-token",
"Accept": "application/json",
},
)
assert response.status_code == 401
def test_middleware_bearer_skipped_when_no_federation_key():
"""Empty federation_key means Bearer tokens are never accepted (falls through to 401)."""
app = _make_federation_app(federation_key="")
client = TestClient(app, base_url="http://192.168.1.1", follow_redirects=False)
response = client.get(
"/protected",
headers={
"Authorization": "Bearer any-token-value",
"Accept": "application/json",
},
)
# Bearer should be skipped when federation_key is empty, falls through to 401
assert response.status_code == 401