Class: Rack::Csrf

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/csrf.rb,
lib/rack/csrf/version.rb

Defined Under Namespace

Classes: InvalidCsrfToken, SessionUnavailable

Constant Summary collapse

CONTENT_TYPE =
(Rack.release >= '2.3' ? 'content-type' : 'Content-Type').freeze
CONTENT_LENGTH =
(Rack.release >= '2.3' ? 'content-length' : 'Content-Length').freeze
VERSION =
'2.7.0'
@@field =
'_csrf'
@@header =
'X_CSRF_TOKEN'
@@key =
'csrf.token'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, opts = {}) ⇒ Csrf

Returns a new instance of Csrf.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/rack/csrf.rb', line 27

def initialize(app, opts = {})
  @app = app

  @raise_if_invalid = opts.fetch(:raise, false)
  @skip_list        = opts.fetch(:skip, []).map {|r| /\A#{r}\Z/i}
  @skip_if          = opts[:skip_if]
  @check_only_list  = opts.fetch(:check_only, []).map {|r| /\A#{r}\Z/i}
  @@field           = opts[:field] if opts[:field]
  @@header          = opts[:header] if opts[:header]
  @@key             = opts[:key] if opts[:key]

  standard_http_methods = %w(POST PUT DELETE PATCH)
  check_also            = opts.fetch(:check_also, [])
  @http_methods = (standard_http_methods + check_also).flatten.uniq
end

Class Method Details

.field ⇒ Object Also known as: csrf_field



63
64
65
# File 'lib/rack/csrf.rb', line 63

def self.field
  @@field
end

.header ⇒ Object Also known as: csrf_header



67
68
69
# File 'lib/rack/csrf.rb', line 67

def self.header
  @@header
end

.key ⇒ Object Also known as: csrf_key



59
60
61
# File 'lib/rack/csrf.rb', line 59

def self.key
  @@key
end

.metatag(env, options = {}) ⇒ Object Also known as: csrf_metatag



79
80
81
82
# File 'lib/rack/csrf.rb', line 79

def self.metatag(env, options = {})
  name = options.fetch(:name, '_csrf')
  %Q(<meta name="#{name}" content="#{token(env)}" />)
end

.tag(env) ⇒ Object Also known as: csrf_tag



75
76
77
# File 'lib/rack/csrf.rb', line 75

def self.tag(env)
  %Q(<input type="hidden" name="#{field}" value="#{token(env)}" />)
end

.token(env) ⇒ Object Also known as: csrf_token



71
72
73
# File 'lib/rack/csrf.rb', line 71

def self.token(env)
  env['rack.session'][key] ||= SecureRandom.urlsafe_base64(32)
end

Instance Method Details

#call(env) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rack/csrf.rb', line 43

def call(env)
  unless env['rack.session']
    fail SessionUnavailable, 'Rack::Csrf depends on session middleware'
  end
  req = Rack::Request.new(env)
  let_it_pass = skip_checking(req) ||
    !@http_methods.include?(req.request_method) ||
    found_a_valid_token?(req)
  if let_it_pass
    @app.call(env)
  else
    fail InvalidCsrfToken if @raise_if_invalid
    [403, {CONTENT_TYPE => 'text/html', CONTENT_LENGTH => '0'}, []]
  end
end