# frozen_string_literal: true require 'securerandom' require 'openssl' require 'logger' module BigSession # This middleware reads BigSession headers from the request and sets/creates a # SessionId usable by the rest of the app class RackMiddleware class << self def activate(header_secret = nil) Rails.application.config.middleware.use ::BigSession::RackMiddleware, header_secret end end def initialize(app, header_secret = nil) @app = app @header_secret = header_secret end def call(env) header_session_id, header_signature = env.values_at( 'HTTP_' + ::BigSession::BIG_SESSION_HEADER_NAME.upcase.gsub(/-/, '_'), 'HTTP_' + ::BigSession::BIG_SESSION_SIGNATURE_HEADER_NAME .upcase.gsub(/-/, '_') ) if header_session_id env['rack.session'][::BigSession::RAILS_SESSION_BIG_SESSION_ID_KEY] = if @header_secret validate_header_session_id(header_session_id, header_signature) else header_session_id end SessionId.set(env['rack.session'][::BigSession::RAILS_SESSION_BIG_SESSION_ID_KEY]) else SessionId.set(env['rack.session'][::BigSession::RAILS_SESSION_BIG_SESSION_ID_KEY]) unless SessionId.current env['rack.session'][::BigSession::RAILS_SESSION_BIG_SESSION_ID_KEY] = SessionId.current end @app.call(env) end private def validate_header_session_id(header_session_id, header_signature) digest = OpenSSL::HMAC.hexdigest('sha256', @header_secret, header_session_id) return header_session_id if digest == header_signature logger = Logger.new(STDOUT) logger.warn('Failed to validate big session header signature.') nil end end end