fix: support authentication through Cloudflare tunnels and reverse proxies (#325)

- Detect when running behind a proxy/tunnel (X-Forwarded-*, CF-Ray headers)
- Use SameSite=None for cookies when proxied to allow cross-origin access
- Properly detect HTTPS when behind proxy using X-Forwarded-Proto
- Fixes authentication not working through Cloudflare tunnels

The issue was that SameSite=Strict/Lax cookies don't work when the origin
changes (which happens with tunnels/proxies). Now we detect proxy headers
and relax the cookie policy to SameSite=None when needed.
This commit is contained in:
Pulse Monitor
2025-08-17 18:11:47 +00:00
parent 4080f8fd05
commit 4e5d28341d
2 changed files with 36 additions and 6 deletions
+20 -4
View File
@@ -252,14 +252,30 @@ func CheckAuth(cfg *config.Config, w http.ResponseWriter, r *http.Request) bool
// Generate CSRF token
csrfToken := generateCSRFToken(token)
// Detect if we're behind a proxy/tunnel (Cloudflare, reverse proxy, etc)
isProxied := r.Header.Get("X-Forwarded-For") != "" ||
r.Header.Get("X-Real-IP") != "" ||
r.Header.Get("CF-Ray") != "" || // Cloudflare
r.Header.Get("X-Forwarded-Proto") != ""
// Determine SameSite policy based on proxy detection
sameSitePolicy := http.SameSiteLaxMode
if isProxied {
// For proxied connections, use None to allow cross-origin cookies
sameSitePolicy = http.SameSiteNoneMode
}
// Determine if connection is secure (required for SameSite=None)
isSecure := r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"
// Set session cookie
http.SetCookie(w, &http.Cookie{
Name: "pulse_session",
Value: token,
Path: "/",
HttpOnly: true,
Secure: r.TLS != nil,
SameSite: http.SameSiteLaxMode,
Secure: isSecure,
SameSite: sameSitePolicy,
MaxAge: 86400, // 24 hours
})
@@ -268,8 +284,8 @@ func CheckAuth(cfg *config.Config, w http.ResponseWriter, r *http.Request) bool
Name: "pulse_csrf",
Value: csrfToken,
Path: "/",
Secure: r.TLS != nil,
SameSite: http.SameSiteStrictMode,
Secure: isSecure,
SameSite: sameSitePolicy,
MaxAge: 86400, // 24 hours
})
+16 -2
View File
@@ -122,13 +122,27 @@ func CheckCSRF(w http.ResponseWriter, r *http.Request) bool {
// Valid session but mismatched CSRF - likely server restart
// Generate a new CSRF token for this session
newToken := generateCSRFToken(cookie.Value)
// Detect if we're behind a proxy/tunnel
isProxied := r.Header.Get("X-Forwarded-For") != "" ||
r.Header.Get("X-Real-IP") != "" ||
r.Header.Get("CF-Ray") != "" ||
r.Header.Get("X-Forwarded-Proto") != ""
sameSitePolicy := http.SameSiteStrictMode
if isProxied {
sameSitePolicy = http.SameSiteNoneMode
}
isSecure := r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"
// Set the new CSRF token as a cookie
http.SetCookie(w, &http.Cookie{
Name: "pulse_csrf",
Value: newToken,
Path: "/",
Secure: r.TLS != nil,
SameSite: http.SameSiteStrictMode,
Secure: isSecure,
SameSite: sameSitePolicy,
MaxAge: 86400, // 24 hours
})
// For this request, we'll be lenient and allow it through