feat: make authentication optional — no tokens = no auth
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:
2026-03-23 13:59:55 +03:00
parent f80f6e9299
commit 4d1bb78c83
14 changed files with 175 additions and 190 deletions
+7 -5
View File
@@ -6,6 +6,7 @@ import {
dom, t, showToast, setWs,
WS_BACKOFF_BASE_MS, WS_BACKOFF_MAX_MS,
WS_MAX_RECONNECT_ATTEMPTS, WS_PING_INTERVAL_MS,
authRequired,
} from './core.js';
import { updateUI, visualizerEnabled, visualizerAvailable, setFrequencyData, stopPositionInterpolation, loadAudioDevices } from './player.js';
import { loadScripts, loadScriptsTable, displayQuickAccess } from './scripts.js';
@@ -62,7 +63,8 @@ export function connectWebSocket(token) {
}
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${protocol}//${window.location.host}/api/media/ws?token=${encodeURIComponent(token)}`;
const wsBase = `${protocol}//${window.location.host}/api/media/ws`;
const wsUrl = token ? `${wsBase}?token=${encodeURIComponent(token)}` : wsBase;
const newWs = new WebSocket(wsUrl);
setWs(newWs);
@@ -134,8 +136,8 @@ export function connectWebSocket(token) {
reconnectTimeout = setTimeout(() => {
const savedToken = localStorage.getItem('media_server_token');
if (savedToken) {
connectWebSocket(savedToken);
if (savedToken || !authRequired) {
connectWebSocket(savedToken || '');
}
}, delay);
} else {
@@ -175,9 +177,9 @@ function hideConnectionBanner() {
export function manualReconnect() {
const savedToken = localStorage.getItem('media_server_token');
if (savedToken) {
if (savedToken || !authRequired) {
wsReconnectAttempts = 0;
hideConnectionBanner();
connectWebSocket(savedToken);
connectWebSocket(savedToken || '');
}
}