feat: make authentication optional — no tokens = no auth
Lint & Test / test (push) Successful in 10s
Lint & Test / test (push) Successful in 10s
When no api_tokens are configured (the new default), all endpoints are accessible without authentication. The frontend detects this via /api/health's auth_required field and skips the login form. - Backend: auth.py skips verification when api_tokens is empty - Frontend: shared getAuthHeaders()/hasCredentials() helpers replace scattered token logic across all JS modules - Health endpoint exposes auth_required for frontend discovery - config.example.yaml ships with tokens commented out - CLI --show-token and startup log reflect disabled state Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+32
-22
@@ -59,9 +59,12 @@ async def lifespan(app: FastAPI):
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info(f"Media Server starting on {settings.host}:{settings.port}")
|
||||
|
||||
# Log all configured tokens
|
||||
for label, token in settings.api_tokens.items():
|
||||
logger.info(f"API Token [{label}]: {token[:8]}...")
|
||||
# Log authentication status
|
||||
if settings.api_tokens:
|
||||
for label, token in settings.api_tokens.items():
|
||||
logger.info(f"API Token [{label}]: {token[:8]}...")
|
||||
else:
|
||||
logger.warning("No API tokens configured — authentication is DISABLED")
|
||||
|
||||
# Start WebSocket status monitor
|
||||
controller = get_media_controller()
|
||||
@@ -129,24 +132,28 @@ def create_app() -> FastAPI:
|
||||
@app.middleware("http")
|
||||
async def token_logging_middleware(request: Request, call_next):
|
||||
"""Extract token label and set in context for logging."""
|
||||
token_label = "unknown"
|
||||
if not settings.api_tokens:
|
||||
token_label_var.set("anonymous")
|
||||
else:
|
||||
token_label = "unknown"
|
||||
|
||||
# Try Authorization header
|
||||
auth_header = request.headers.get("authorization", "")
|
||||
if auth_header.startswith("Bearer "):
|
||||
token = auth_header[7:]
|
||||
label = get_token_label(token)
|
||||
if label:
|
||||
token_label = label
|
||||
# Try Authorization header
|
||||
auth_header = request.headers.get("authorization", "")
|
||||
if auth_header.startswith("Bearer "):
|
||||
token = auth_header[7:]
|
||||
label = get_token_label(token)
|
||||
if label:
|
||||
token_label = label
|
||||
|
||||
# Try query parameter (for artwork endpoint)
|
||||
elif "token" in request.query_params:
|
||||
token = request.query_params["token"]
|
||||
label = get_token_label(token)
|
||||
if label:
|
||||
token_label = label
|
||||
# Try query parameter (for artwork endpoint)
|
||||
elif "token" in request.query_params:
|
||||
token = request.query_params["token"]
|
||||
label = get_token_label(token)
|
||||
if label:
|
||||
token_label = label
|
||||
|
||||
token_label_var.set(token_label)
|
||||
|
||||
token_label_var.set(token_label)
|
||||
response = await call_next(request)
|
||||
return response
|
||||
|
||||
@@ -215,14 +222,17 @@ def main():
|
||||
if args.generate_config:
|
||||
config_path = generate_default_config()
|
||||
print(f"Configuration file generated at: {config_path}")
|
||||
print("API Token has been saved to the config file.")
|
||||
print("Authentication is disabled by default. Add api_tokens to enable it.")
|
||||
return
|
||||
|
||||
if args.show_token:
|
||||
print(f"Config directory: {get_config_dir()}")
|
||||
print("\nAPI Tokens:")
|
||||
for label, token in settings.api_tokens.items():
|
||||
print(f" {label:20} {token}")
|
||||
if settings.api_tokens:
|
||||
print("\nAPI Tokens:")
|
||||
for label, token in settings.api_tokens.items():
|
||||
print(f" {label:20} {token}")
|
||||
else:
|
||||
print("\nAuthentication is DISABLED (no tokens configured)")
|
||||
return
|
||||
|
||||
uvicorn.run(
|
||||
|
||||
Reference in New Issue
Block a user