Fix router to allow frontend pages without authentication

When a request for /login (or any other frontend route) comes in without
proper Accept headers (like from curl or some browsers), the server was
returning 'Authentication required' text instead of serving the frontend HTML.

This is because the router was checking authentication before serving ANY
non-API route, including frontend pages like /login, /dashboard, etc.

The fix: Frontend routes should always be served without backend auth checks.
The authentication logic runs in the frontend JavaScript after the page loads.

Backend auth should only block:
- API endpoints (/api/*)
- WebSocket connections (/ws*, /socket.io/*)
- Download endpoints (/download/*)
- Special scripts (/install-*.sh, etc.)

All other routes are frontend pages that need to be served to everyone so
the login page can load and handle auth in the browser.

This fixes the integration tests where Playwright couldn't see the login
form because the server was rejecting the /login request before serving HTML.

Related to #695 (release workflow integration tests)
This commit is contained in:
rcourtman 2025-11-12 11:30:22 +00:00
parent 9ef3092809
commit 48f8473200

View file

@ -1297,6 +1297,19 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Also allow static assets without auth (JS, CSS, etc)
// These MUST be accessible for the login page to work
// Frontend routes (non-API, non-download) should also be public
// because authentication is handled by the frontend after page load
isFrontendRoute := !strings.HasPrefix(req.URL.Path, "/api/") &&
!strings.HasPrefix(req.URL.Path, "/ws") &&
!strings.HasPrefix(req.URL.Path, "/socket.io/") &&
!strings.HasPrefix(req.URL.Path, "/download/") &&
req.URL.Path != "/simple-stats" &&
req.URL.Path != "/install-docker-agent.sh" &&
req.URL.Path != "/install-container-agent.sh" &&
req.URL.Path != "/install-host-agent.sh" &&
req.URL.Path != "/install-host-agent.ps1" &&
req.URL.Path != "/uninstall-host-agent.ps1"
isStaticAsset := strings.HasPrefix(req.URL.Path, "/assets/") ||
strings.HasPrefix(req.URL.Path, "/@vite/") ||
strings.HasPrefix(req.URL.Path, "/@solid-refresh") ||
@ -1314,7 +1327,7 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
strings.HasSuffix(req.URL.Path, ".mjs") ||
strings.HasSuffix(req.URL.Path, ".jsx")
isPublic := isStaticAsset
isPublic := isStaticAsset || isFrontendRoute
for _, path := range publicPaths {
if normalizedPath == path {
isPublic = true