Inspired by CorsGate as introduced by Mixmax, this Gem implements the same
CSRF-protection for Rack. In short, we use Rack::Cors
to configure whether or not requests are allowed to occur, and
we enforce them via this middleware. Requests that are potential threats are blocked with a 403
response. Please read
Using CORS policies to implement CSRF protection for the philosophy behind this
middleware.
Install the gem:
gem install rack-corsgate
Or in your Gemfile:
gem 'rack-corsgate'
Dependencies
Your application must have Rack::Cors
available. See: Rack CORS Middleware
Follow the configuration requirements given in its readme.
CorsGate is actually two middleware functions:
- The
CorsGateOriginProcessor
middleware checks if we have an origin header. If we don't, it will try to determine the origin based on theReferer
header. This middleware should be triggered beforeRack::Cors
. - The
CorsGate
middleware enforces the result of the CORS test on the request, by actively blocking requests that are potential CSRF-attacks. This middleware should be triggered afterRack::Cors
.
The easiest way to sandwich Rack::Cors with these two middlewares is as follows:
# Rack::CorsGate.use middleware, opts = {}, &forbidden_handler
Rack::CorsGate.use config.middleware
This is essentially a shortcut for the following:
config.middleware.insert_before Rack::Cors, Rack::CorsGateOriginProcessor
config.middleware.insert_after Rack::Cors, Rack::CorsGate
The options hash passed to Rack::CorsGate.use
is passed on to both middlewares. The block applies to Rack::CorsGate
only (see API below).
API
config.middleware.insert_before Rack::Cors, Rack::CorsGateOriginProcessor, { remove_null_origin: false }
Options:
remove_null_origin
(boolean, default: false): Treatsnull
(string) origin headers as if no origin header was set.
config.middleware.insert_after Rack::Cors, Rack::CorsGate, { simulation: false, strict: false, allow_safe: true } do |env, origin, method|
# env: https://www.rubydoc.info/github/rack/rack/master/file/SPEC#label-The+Environment
Rails.logger.warn("Blocked #{method} request from origin #{origin} to #{env['PATH_INFO']}")
end
Options:
simulation
(boolean, default: false): Allows potential attacks to be carried out as if the middleware wasn't there. This can be useful during implementation trials and tests (see also the block signature below).strict
(boolean, default: false): If true, requires an origin to be present on all requests. Note that a Referer header will stand in for a missing Origin header if the CorsGateOriginProcessor is used.allow_safe
(boolean, default: false): If true, allowsGET
andHEAD
requests through, even if the origin is not allowed by CORS, or if the Origin header is missing.
Block |env, origin, method|
:
This optional block gets invoked whenever a request is about to be rejected (even in simulation mode).
MIT