mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-22 19:23:31 +00:00
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:
+20
-4
@@ -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
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user