Class: Otto::Security::CSRFEnforcementWrapper

Inherits:
Object
  • Object
show all
Includes:
CSRFValidation
Defined in:
lib/otto/security/csrf_enforcement_wrapper.rb

Overview

Per-route CSRF enforcement, applied at the handler layer.

CSRF enforcement lives here rather than in the global +CSRFMiddleware+ because +csrf=exempt+ is a per-route option: it is only known once a route has been matched (the middleware runs ahead of route matching and never sees route options, so a global block could not honor exemption — issue #186). This wrapper runs after matching, alongside +RouteAuthWrapper+, where +route_definition.csrf_exempt?+ is directly available. It is composed by +HandlerFactory+ only when CSRF protection is enabled, and wraps outside +RouteAuthWrapper+ so a forged unsafe request is rejected before any authentication work runs.

The global +CSRFMiddleware+ retains only token injection into HTML responses (a response-shaping concern that is method/content-type based, not route based, so it stays global).

Constant Summary

Constants included from CSRFValidation

Otto::Security::CSRFValidation::CSRF_ERROR_BODY, Otto::Security::CSRFValidation::SAFE_METHODS

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(wrapped_handler, route_definition, config) ⇒ CSRFEnforcementWrapper

Returns a new instance of CSRFEnforcementWrapper.

Parameters:



32
33
34
35
36
# File 'lib/otto/security/csrf_enforcement_wrapper.rb', line 32

def initialize(wrapped_handler, route_definition, config)
  @wrapped_handler  = wrapped_handler
  @route_definition = route_definition
  @config           = config
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



27
28
29
# File 'lib/otto/security/csrf_enforcement_wrapper.rb', line 27

def config
  @config
end

#route_definitionObject (readonly)

Returns the value of attribute route_definition.



27
28
29
# File 'lib/otto/security/csrf_enforcement_wrapper.rb', line 27

def route_definition
  @route_definition
end

#wrapped_handlerObject (readonly)

Returns the value of attribute wrapped_handler.



27
28
29
# File 'lib/otto/security/csrf_enforcement_wrapper.rb', line 27

def wrapped_handler
  @wrapped_handler
end

Instance Method Details

#call(env, extra_params = {}) ⇒ Array

Returns Rack response tuple.

Parameters:

  • env (Hash)

    Rack environment

  • extra_params (Hash) (defaults to: {})

    Additional parameters passed through to the handler

Returns:

  • (Array)

    Rack response tuple



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/otto/security/csrf_enforcement_wrapper.rb', line 41

def call(env, extra_params = {})
  return wrapped_handler.call(env, extra_params) unless enforce?(env)

  request = Otto::Request.new(env)
  return wrapped_handler.call(env, extra_params) if valid_csrf_token?(request)

  Otto.structured_log(:warn, 'CSRF validation failed',
    Otto::LoggingHelpers.request_context(env).merge(
      handler: route_definition.definition,
      referrer: request.referrer
    ))
  csrf_error_response
end