diff --git a/app.rb b/app.rb index f087b58..0845779 100644 --- a/app.rb +++ b/app.rb @@ -34,6 +34,21 @@ module Maptool set :sessions, httponly: true, secure: production?, same_site: :lax, secret: ENV.fetch("SESSION_SECRET") { SecureRandom.hex(32) } + # Sinatra enables Rack::Protection::SessionHijacking by default once + # sessions are on: it fingerprints a session to the User-Agent header + # seen on the request that first wrote to it, and *silently* empties + # the session (no exception, nothing logged) on any later request + # where that header doesn't match — which is exactly what a login + # behind production's reverse proxy hit: the OAuth callback set + # session[:user] fine, but the very next ordinary page load (or even a + # plain refresh) came back logged out with nothing in the logs to + # explain it. Its own docs already admit every header it can check is + # spoofable anyway ("will not prevent determined hijacking attempts") + # — losing it is a minor tradeoff for a login that actually stays + # logged in. Every other Rack::Protection check (XSS header, path + # traversal, JSON CSRF, frame options, ...) stays on. + set :protection, except: [:session_hijacking] + # Cache-busts /js and /css requests: browsers (and a caching proxy in # front of production, see docs/deployment.adoc) hang onto static # assets for hours, so without this a deploy that changes app.js/css