From 346c736112bc0a7bcf5f3d326b5de24f4e388554 Mon Sep 17 00:00:00 2001 From: Pulse Monitor Date: Sat, 23 Aug 2025 22:47:30 +0000 Subject: [PATCH] fix: auto-registration now works with secured Pulse instances The temporary auth tokens generated by authenticated users are now properly validated even when Pulse has authentication enabled. This fixes the issue where fresh installs (which are secured by default) couldn't use the auto-registration feature. --- VERSION | 2 +- internal/api/config_handlers.go | 19 +++++++++++++++++-- internal/api/router.go | 6 ++++++ internal/updates/version.go | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 93d7d00ec..81dd1e5cc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.7.5 \ No newline at end of file +4.7.6 \ No newline at end of file diff --git a/internal/api/config_handlers.go b/internal/api/config_handlers.go index 82bf36e99..a1aea1d01 100644 --- a/internal/api/config_handlers.go +++ b/internal/api/config_handlers.go @@ -2515,8 +2515,16 @@ func (h *ConfigHandlers) HandleAutoRegister(w http.ResponseWriter, r *http.Reque // First check for setup code/auth token in the request if authCode != "" { codeHash := internalauth.HashAPIToken(authCode) + log.Debug(). + Str("authCode", authCode). + Str("codeHash", codeHash[:8]+"..."). + Msg("Checking auth token") h.codeMutex.Lock() setupCode, exists := h.setupCodes[codeHash] + log.Debug(). + Bool("exists", exists). + Int("totalCodes", len(h.setupCodes)). + Msg("Setup code lookup result") if exists && !setupCode.Used && time.Now().Before(setupCode.ExpiresAt) { // Validate that the code matches the node type // Note: We don't validate the host anymore as it may differ between @@ -2556,8 +2564,15 @@ func (h *ConfigHandlers) HandleAutoRegister(w http.ResponseWriter, r *http.Reque } // If still not authenticated and auth is required, reject - if !authenticated && h.config.APIToken != "" { - log.Warn().Str("ip", r.RemoteAddr).Msg("Unauthorized auto-register attempt - invalid or missing setup code") + // BUT: Always allow if a valid setup code/auth token was provided (even if expired/used) + // This ensures the error message is accurate + if !authenticated && h.config.APIToken != "" && authCode == "" { + log.Warn().Str("ip", r.RemoteAddr).Msg("Unauthorized auto-register attempt - no authentication provided") + http.Error(w, "Pulse requires authentication", http.StatusUnauthorized) + return + } else if !authenticated && h.config.APIToken != "" { + // Had a code but it didn't validate + log.Warn().Str("ip", r.RemoteAddr).Msg("Unauthorized auto-register attempt - invalid or expired setup code") http.Error(w, "Invalid or expired setup code", http.StatusUnauthorized) return } diff --git a/internal/api/router.go b/internal/api/router.go index 955632897..bd0137f90 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -796,6 +796,12 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { isPublic = true } + // Auto-register endpoint needs to be public (validates tokens internally) + // BUT the tokens must be generated by authenticated users via setup-script-url + if req.URL.Path == "/api/auto-register" { + isPublic = true + } + // Special case: quick-setup should be accessible to check if already configured // The handler itself will verify if setup should be skipped if req.URL.Path == "/api/security/quick-setup" && req.Method == http.MethodPost { diff --git a/internal/updates/version.go b/internal/updates/version.go index 8b7dbd768..8c0485ed9 100644 --- a/internal/updates/version.go +++ b/internal/updates/version.go @@ -164,7 +164,7 @@ func GetCurrentVersion() (*VersionInfo, error) { } // Final fallback - version := "4.7.5" + version := "4.7.6" channel := "stable" if strings.Contains(strings.ToLower(version), "rc") { channel = "rc"