rack_csrf 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,15 @@
1
+ # v2.3.0 (2011-10-23)
2
+
3
+ * Updated examples' Gemfiles.
4
+ * Moved to use the RDoc gem.
5
+ * new option :check_only (courtesy of [ghermeto](https://github.com/ghermeto))
6
+ * Cuba example.
7
+ * Changed request checking to look at GET+POST data.
8
+ * Added support for custom HTTP methods.
9
+ * Promoted public methods' shorter aliases to main API.
10
+
11
+
12
+
1
13
  # v2.2.0 (2011-04-12)
2
14
 
3
15
  * Simplified specs and some Cucumber's steps.
@@ -34,6 +34,20 @@ The following options allow you to tweak Rack::Csrf.
34
34
 
35
35
  Default value: false.
36
36
 
37
+ [<tt>:check_only</tt>]
38
+ By default, Rack::Csrf checks every POST, PUT, DELETE and PATCH request;
39
+ passing an array of HTTP method/URL (regular expressions allowed) to this
40
+ option you can change this behavior to *only* check the items on this list.
41
+
42
+ use Rack::Csrf, :check_only => ['POST:/checking', 'PUT:/me_too',
43
+ 'DELETE:/cars/.*\.xml', 'PATCH:/this/.*/too']
44
+
45
+ Please, note that the regular expressions are not escaped and it is your
46
+ duty to write them correctly. Empty PATH_INFO (see Rack's spec for details)
47
+ is treated as '/' for this check.
48
+
49
+ Default value: empty.
50
+
37
51
  [<tt>:skip</tt>]
38
52
  By default, Rack::Csrf checks every POST, PUT, DELETE and PATCH request;
39
53
  passing an array of HTTP method/URL (regular expressions allowed) to this
@@ -64,6 +78,15 @@ The following options allow you to tweak Rack::Csrf.
64
78
 
65
79
  Default value: csrf.token
66
80
 
81
+ [<tt>:check_also</tt>]
82
+ By passing an array of uppercase strings to this option you can add them to
83
+ the list of HTTP methods which "mark" requests that must be searched for the
84
+ anti-forging token.
85
+
86
+ use Rack::Csrf, :check_also => %w(WHATEVER YOU WANT EVEN GET)
87
+
88
+ Default value: empty
89
+
67
90
  The <tt>:browser_only</tt> option has been removed; you do not need to edit
68
91
  any rackup file because Rack::Csrf simply ignores unknown options. Changes
69
92
  introduced in Rack version 1.1.0 tightened the parsing of POST params, so
@@ -80,19 +103,19 @@ The ill devised <tt>:browser_only</tt> option could have been used to
80
103
  The following class methods try to ease the insertion of the anti-forging
81
104
  token.
82
105
 
83
- [<tt>Rack::Csrf.csrf_key</tt> (also <tt>Rack::Csrf.key</tt>)]
106
+ [<tt>Rack::Csrf.key</tt> (also <tt>Rack::Csrf.csrf_key</tt>)]
84
107
  Returns the name of the key used to store/retrieve the token from the Rack
85
108
  session.
86
109
 
87
- [<tt>Rack::Csrf.csrf_field</tt> (also <tt>Rack::Csrf.field</tt>)]
110
+ [<tt>Rack::Csrf.field</tt> (also <tt>Rack::Csrf.csrf_field</tt>)]
88
111
  Returns the name of the field that must be present in the request.
89
112
 
90
- [<tt>Rack::Csrf.csrf_token(env)</tt> (also <tt>Rack::Csrf.token(env)</tt>)]
113
+ [<tt>Rack::Csrf.token(env)</tt> (also <tt>Rack::Csrf.csrf_token(env)</tt>)]
91
114
  Given the request's environment, it generates a random token, stuffs it in
92
115
  the session and returns it to the caller or simply retrieves the already
93
116
  stored one.
94
117
 
95
- [<tt>Rack::Csrf.csrf_tag(env)</tt> (also <tt>Rack::Csrf.tag(env)</tt>)]
118
+ [<tt>Rack::Csrf.tag(env)</tt> (also <tt>Rack::Csrf.csrf_tag(env)</tt>)]
96
119
  Given the request's environment, it generates a small HTML fragment to
97
120
  insert the token in a standard form like an hidden input field with the
98
121
  right value already entered for you.
@@ -107,7 +130,7 @@ framework; see the various README files for other details.
107
130
 
108
131
  If you want to help:
109
132
 
110
- * fork the project[http://github.com/baldowl/rack_csrf] on GitHub;
133
+ * fork the project[https://github.com/baldowl/rack_csrf] on GitHub;
111
134
  * work in a topic branch;
112
135
  * add features/specs for your additions or bug fixes;
113
136
  * write your additions/bug fixes;
@@ -115,7 +138,7 @@ If you want to help:
115
138
  * send me a pull request for the topic branch.
116
139
 
117
140
  If you have any issue, please post them on the {project's issue
118
- list}[http://github.com/baldowl/rack_csrf] on GitHub.
141
+ list}[https://github.com/baldowl/rack_csrf] on GitHub.
119
142
 
120
143
  == Warning! Warning! Warning!
121
144
 
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rake/clean'
2
2
  require 'cucumber/rake/task'
3
3
  require 'rspec/core/rake_task'
4
- require 'rake/rdoctask'
4
+ require 'rdoc/task'
5
5
  require 'jeweler'
6
6
 
7
7
  Cucumber::Rake::Task.new :features
@@ -14,9 +14,10 @@ task :default => :spec
14
14
 
15
15
  version = File.exists?('VERSION') ? File.read('VERSION').strip : ''
16
16
 
17
- Rake::RDocTask.new :doc do |rdoc|
17
+ RDoc::Task.new :doc do |rdoc|
18
18
  rdoc.rdoc_dir = 'doc'
19
19
  rdoc.title = "Rack::Csrf #{version}"
20
+ rdoc.main = 'README.rdoc'
20
21
  rdoc.rdoc_files.include('README.rdoc', 'LICENSE.rdoc')
21
22
  rdoc.rdoc_files.include('lib/**/*.rb')
22
23
  end
@@ -28,12 +29,13 @@ Jeweler::Tasks.new do |gem|
28
29
  gem.license = 'MIT'
29
30
  gem.authors = 'Emanuele Vicentini'
30
31
  gem.email = 'emanuele.vicentini@gmail.com'
31
- gem.homepage = 'http://github.com/baldowl/rack_csrf'
32
+ gem.homepage = 'https://github.com/baldowl/rack_csrf'
32
33
  gem.rubyforge_project = 'rackcsrf'
33
34
  gem.add_dependency 'rack', '>= 0.9'
34
35
  gem.add_development_dependency 'cucumber', '>= 0.1.13'
35
36
  gem.add_development_dependency 'rack-test'
36
37
  gem.add_development_dependency 'rspec', '>= 2.0.0'
38
+ gem.add_development_dependency 'rdoc', '>= 2.4.2'
37
39
  gem.rdoc_options << '--line-numbers' << '--inline-source' << '--title' <<
38
40
  "Rack::Csrf #{version}" << '--main' << 'README.rdoc'
39
41
  gem.test_files.clear
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.2.0
1
+ 2.3.0
@@ -1,4 +1,4 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'camping', '2.1'
4
- gem 'markaby', '0.7.1'
3
+ gem 'camping', '>= 2.1', '<= 2.1.467'
4
+ gem 'markaby', '>= 0.7.1', '<= 0.7.2'
@@ -37,7 +37,7 @@ module LittleApp
37
37
  form :action => URL(Response), :method => :post do
38
38
  h1 'Spit your utterance!'
39
39
  input :name => :utterance, :type => :text
40
- text Rack::Csrf.csrf_tag(@env)
40
+ text Rack::Csrf.tag(@env)
41
41
  p {
42
42
  input :type => :submit, :value => :Send!
43
43
  }
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'cuba', '2.1.0'
@@ -0,0 +1,11 @@
1
+ = How to use Rack::Csrf with Cuba
2
+
3
+ This is a mini Cuba application with two slightly different rackup files.
4
+ Beside Rack you only need Cuba to try them, so, assuming you have Bundler
5
+ installed, run:
6
+
7
+ $ bundle install
8
+ $ bundle exec rackup -p 3000 config.ru
9
+ $ bundle exec rackup -p 3000 config-with-raise.ru
10
+
11
+ Tested with Cuba versions listed in the Gemfile.
@@ -0,0 +1,17 @@
1
+ Cuba.define do
2
+ on get do
3
+ on '' do
4
+ res.write render('views/form.erb')
5
+ end
6
+
7
+ on 'notworking' do
8
+ res.write render('views/form_not_working.erb')
9
+ end
10
+ end
11
+
12
+ on post do
13
+ on 'response', param(:utterance), param(Rack::Csrf.field) do |utterance, csrf|
14
+ res.write render('views/response.erb', :utterance => utterance, :csrf => csrf)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ require 'cuba'
2
+ $: << File.join(File.dirname(__FILE__), '../../lib')
3
+ require 'rack/csrf'
4
+
5
+ Cuba.use Rack::ShowExceptions
6
+ Cuba.use Rack::Session::Cookie
7
+ Cuba.use Rack::Csrf, :raise => true
8
+
9
+ require 'app'
10
+
11
+ run Cuba
@@ -0,0 +1,10 @@
1
+ require 'cuba'
2
+ $: << File.join(File.dirname(__FILE__), '../../lib')
3
+ require 'rack/csrf'
4
+
5
+ Cuba.use Rack::Session::Cookie
6
+ Cuba.use Rack::Csrf
7
+
8
+ require 'app'
9
+
10
+ run Cuba
@@ -0,0 +1,8 @@
1
+ <form action="/response" method="post">
2
+ <h1>Spit your utterance!</h1>
3
+ <input type="text" name="utterance">
4
+ <%= Rack::Csrf.tag(env) %>
5
+ <p><input type="submit" value="Send!"></p>
6
+ </form>
7
+
8
+ <p>Try also the <a href="/notworking">not working</a> form!</p>
@@ -0,0 +1,7 @@
1
+ <form action="/response" method="post">
2
+ <h1>Spit your utterance!</h1>
3
+ <input type="text" name="utterance">
4
+ <p><input type="submit" value="Send!"></p>
5
+ </form>
6
+
7
+ <p>Try also the <a href="/">working</a> form!</p>
@@ -0,0 +1,5 @@
1
+ <p>It seems you've just said: <em><%= utterance %></em></p>
2
+
3
+ <p>Here's the anti-CSRF token stuffed in the session: <strong><%= csrf %></strong></p>
4
+
5
+ <p><a href='/'>Back</a></p>
@@ -1,3 +1,3 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'innate', '>= 2009.07', '<= 2011.01'
3
+ gem 'innate', '>= 2009.07', '<= 2011.04'
@@ -5,6 +5,6 @@ class LittleApp
5
5
 
6
6
  def response
7
7
  redirect_referer unless request.post?
8
- @utterance, @csrf = request[:utterance, Rack::Csrf.csrf_field]
8
+ @utterance, @csrf = request[:utterance, Rack::Csrf.field]
9
9
  end
10
10
  end
@@ -1,7 +1,7 @@
1
1
  <form action="/response" method="post">
2
2
  <h1>Spit your utterance!</h1>
3
3
  <input type="text" name="utterance">
4
- <%= Rack::Csrf.csrf_tag(request.env) %>
4
+ <%= Rack::Csrf.tag(request.env) %>
5
5
  <p><input type="submit" value="Send!"></p>
6
6
  </form>
7
7
 
@@ -1,3 +1,3 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'rack', '>= 1.0.0', '<= 1.2.2'
3
+ gem 'rack', '>= 1.0.0', '<= 1.3.5'
@@ -3,7 +3,7 @@ class LittleApp
3
3
  <form action="/response" method="post">
4
4
  <h1>Spit your utterance!</h1>
5
5
  <input type="text" name="utterance">
6
- <%= Rack::Csrf.csrf_tag(env) %>
6
+ <%= Rack::Csrf.tag(env) %>
7
7
  <p><input type="submit" value="Send!"></p>
8
8
  </form>
9
9
 
@@ -38,7 +38,7 @@ class LittleApp
38
38
  end
39
39
  elsif req.post?
40
40
  utterance = req['utterance']
41
- csrf = req[Rack::Csrf.csrf_field]
41
+ csrf = req[Rack::Csrf.field]
42
42
  Rack::Response.new(@response.result(binding)).finish
43
43
  end
44
44
  end
@@ -1,3 +1,3 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'sinatra', '>= 0.9.4', '<= 1.2.1'
3
+ gem 'sinatra', '>= 0.9.4', '<= 1.3.1'
@@ -8,5 +8,5 @@ end
8
8
 
9
9
  post '/response' do
10
10
  erb :response, :locals => {:utterance => params[:utterance],
11
- :csrf => params[Rack::Csrf.csrf_field]}
11
+ :csrf => params[Rack::Csrf.field]}
12
12
  end
@@ -1,7 +1,7 @@
1
1
  <form action="/response" method="post">
2
2
  <h1>Spit your utterance!</h1>
3
3
  <input type="text" name="utterance">
4
- <%= Rack::Csrf.csrf_tag(env) %>
4
+ <%= Rack::Csrf.tag(env) %>
5
5
  <p><input type="submit" value="Send!"></p>
6
6
  </form>
7
7
 
@@ -0,0 +1,28 @@
1
+ Feature: Check only some specific requests
2
+
3
+ Background:
4
+ Given a rack with the anti-CSRF middleware and the :check_only option
5
+ | pair |
6
+ | POST:/check/this |
7
+
8
+ Scenario: Blocking that specific request
9
+ When it receives a POST request for /check/this without the CSRF token
10
+ Then it responds with 403
11
+
12
+ Scenario Outline: Not blocking other requests
13
+ When it receives a <method> request for <path> without the CSRF token
14
+ Then it lets it pass untouched
15
+
16
+ Examples:
17
+ | method | path |
18
+ | GET | /check/this |
19
+ | PUT | /check/this |
20
+ | PATCH | /check/this |
21
+ | DELETE | /check/this |
22
+ | CUSTOM | /check/this |
23
+ | GET | /another/one |
24
+ | POST | /another/one |
25
+ | PUT | /another/one |
26
+ | PATCH | /another/one |
27
+ | DELETE | /another/one |
28
+ | CUSTOM | /another/one |
@@ -0,0 +1,62 @@
1
+ Feature: Handling custom HTTP methods
2
+
3
+ Background:
4
+ Given a rack with the anti-CSRF middleware and the :check_also option
5
+ | method |
6
+ | ME |
7
+ | YOU |
8
+
9
+ Scenario Outline: Blocking "standard" requests without the token
10
+ When it receives a <method> request without the CSRF token
11
+ Then it responds with 403
12
+ And the response body is empty
13
+
14
+ Examples:
15
+ | method |
16
+ | POST |
17
+ | PUT |
18
+ | DELETE |
19
+ | PATCH |
20
+
21
+ Scenario Outline: Blocking "standard" requests with the wrong token
22
+ When it receives a <method> request with the wrong CSRF token
23
+ Then it responds with 403
24
+ And the response body is empty
25
+
26
+ Examples:
27
+ | method |
28
+ | POST |
29
+ | PUT |
30
+ | DELETE |
31
+ | PATCH |
32
+
33
+ Scenario Outline: Blocking requests without the token
34
+ When it receives a <method> request without the CSRF token
35
+ Then it responds with 403
36
+ And the response body is empty
37
+
38
+ Examples:
39
+ | method |
40
+ | ME |
41
+ | YOU |
42
+
43
+ Scenario Outline: Blocking requests with the wrong token
44
+ When it receives a <method> request with the wrong CSRF token
45
+ Then it responds with 403
46
+ And the response body is empty
47
+
48
+ Examples:
49
+ | method |
50
+ | ME |
51
+ | YOU |
52
+
53
+ Scenario Outline: Letting pass "unknown" and safe requests without the token
54
+ When it receives a <method> request without the CSRF token
55
+ Then it lets it pass untouched
56
+
57
+ Examples:
58
+ | method |
59
+ | HIM |
60
+ | HER |
61
+ | GET |
62
+ | OPTIONS |
@@ -1,17 +1,21 @@
1
1
  Feature: Handling of the HTTP requests returning an empty response
2
2
 
3
- Scenario: GET request with CSRF token
3
+ Background:
4
4
  Given a rack with the anti-CSRF middleware
5
- When it receives a GET request with the CSRF token
5
+
6
+ Scenario: GET request with the right CSRF token
7
+ When it receives a GET request with the right CSRF token
8
+ Then it lets it pass untouched
9
+
10
+ Scenario: GET request with the wrong CSRF token
11
+ When it receives a GET request with the wrong CSRF token
6
12
  Then it lets it pass untouched
7
13
 
8
14
  Scenario: GET request without CSRF token
9
- Given a rack with the anti-CSRF middleware
10
15
  When it receives a GET request without the CSRF token
11
16
  Then it lets it pass untouched
12
17
 
13
18
  Scenario Outline: Handling request without CSRF token
14
- Given a rack with the anti-CSRF middleware
15
19
  When it receives a <method> request without the CSRF token
16
20
  Then it responds with 403
17
21
  And the response body is empty
@@ -24,7 +28,6 @@ Feature: Handling of the HTTP requests returning an empty response
24
28
  | PATCH |
25
29
 
26
30
  Scenario Outline: Handling request with the right CSRF token
27
- Given a rack with the anti-CSRF middleware
28
31
  When it receives a <method> request with the right CSRF token
29
32
  Then it lets it pass untouched
30
33
 
@@ -36,7 +39,6 @@ Feature: Handling of the HTTP requests returning an empty response
36
39
  | PATCH |
37
40
 
38
41
  Scenario Outline: Handling request with the wrong CSRF token
39
- Given a rack with the anti-CSRF middleware
40
42
  When it receives a <method> request with the wrong CSRF token
41
43
  Then it responds with 403
42
44
  And the response body is empty
@@ -0,0 +1,20 @@
1
+ Feature: Inspecting also GET requests
2
+
3
+ Background:
4
+ Given a rack with the anti-CSRF middleware and the :check_also option
5
+ | method |
6
+ | GET |
7
+
8
+ Scenario: GET request with the right CSRF token
9
+ When it receives a GET request with the right CSRF token
10
+ Then it lets it pass untouched
11
+
12
+ Scenario: GET request with the wrong CSRF token
13
+ When it receives a GET request with the wrong CSRF token
14
+ Then it responds with 403
15
+ And the response body is empty
16
+
17
+ Scenario: GET request without the CSRF token
18
+ When it receives a GET request without the CSRF token
19
+ Then it responds with 403
20
+ And the response body is empty
@@ -1,12 +1,13 @@
1
1
  Feature: Handling of the HTTP requests raising an exception
2
2
 
3
- Scenario: GET request without CSRF token
3
+ Background:
4
4
  Given a rack with the anti-CSRF middleware and the :raise option
5
+
6
+ Scenario: GET request without CSRF token
5
7
  When it receives a GET request without the CSRF token
6
8
  Then it lets it pass untouched
7
9
 
8
10
  Scenario Outline: Handling request without CSRF token
9
- Given a rack with the anti-CSRF middleware and the :raise option
10
11
  When it receives a <method> request without the CSRF token
11
12
  Then there is no response
12
13
  And an exception is climbing up the stack
@@ -19,7 +20,6 @@ Feature: Handling of the HTTP requests raising an exception
19
20
  | PATCH |
20
21
 
21
22
  Scenario Outline: Handling request with the right CSRF token
22
- Given a rack with the anti-CSRF middleware and the :raise option
23
23
  When it receives a <method> request with the right CSRF token
24
24
  Then it lets it pass untouched
25
25
 
@@ -31,7 +31,6 @@ Feature: Handling of the HTTP requests raising an exception
31
31
  | PATCH |
32
32
 
33
33
  Scenario Outline: Handling request with the wrong CSRF token
34
- Given a rack with the anti-CSRF middleware and the :raise option
35
34
  When it receives a <method> request with the wrong CSRF token
36
35
  Then there is no response
37
36
  And an exception is climbing up the stack
@@ -32,3 +32,19 @@ Feature: Setup of the middleware
32
32
  Given a rack with the session middleware
33
33
  When I insert the anti-CSRF middleware with the :key option
34
34
  Then I get a fully functional rack
35
+
36
+ Scenario: Setup with the :check_also option
37
+ Given a rack with the session middleware
38
+ When I insert the anti-CSRF middleware with the :check_also option
39
+ | method |
40
+ | ME |
41
+ | YOU |
42
+ Then I get a fully functional rack
43
+
44
+ Scenario: Setup with the :check_only option
45
+ Given a rack with the session middleware
46
+ When I insert the anti-CSRF middleware with the :check_only option
47
+ | route |
48
+ | POST:/check/me |
49
+ | PUT:/check/this/too |
50
+ Then I get a fully functional rack
@@ -1,12 +1,7 @@
1
- When /^it receives a GET request (with|without) the CSRF token$/ do |prep|
2
- params = prep == 'with' ? {Rack::Csrf.csrf_field => 'whatever'} : {}
3
- @browser.get '/', :params => params
4
- end
5
-
6
1
  # Yes, they're not as DRY as possible, but I think they're more readable than
7
2
  # a single step definition with a few captures and more complex checkings.
8
3
 
9
- When /^it receives a (POST|PUT|DELETE|PATCH) request without the CSRF token$/ do |http_method|
4
+ When /^it receives a (.*) request without the CSRF token$/ do |http_method|
10
5
  begin
11
6
  @browser.request '/', :method => http_method
12
7
  rescue Exception => e
@@ -14,7 +9,7 @@ When /^it receives a (POST|PUT|DELETE|PATCH) request without the CSRF token$/ do
14
9
  end
15
10
  end
16
11
 
17
- When /^it receives a (POST|PUT|DELETE|PATCH) request for (.+) without the CSRF token$/ do |http_method, path|
12
+ When /^it receives a (.*) request for (.+) without the CSRF token$/ do |http_method, path|
18
13
  begin
19
14
  @browser.request path, :method => http_method
20
15
  rescue Exception => e
@@ -22,22 +17,22 @@ When /^it receives a (POST|PUT|DELETE|PATCH) request for (.+) without the CSRF t
22
17
  end
23
18
  end
24
19
 
25
- When /^it receives a (POST|PUT|DELETE|PATCH) request with the right CSRF token$/ do |http_method|
20
+ When /^it receives a (.*) request with the right CSRF token$/ do |http_method|
26
21
  @browser.request '/', :method => http_method,
27
- 'rack.session' => {Rack::Csrf.csrf_key => 'right_token'},
28
- :params => {Rack::Csrf.csrf_field => 'right_token'}
22
+ 'rack.session' => {Rack::Csrf.key => 'right_token'},
23
+ :params => {Rack::Csrf.field => 'right_token'}
29
24
  end
30
25
 
31
- When /^it receives a (POST|PUT|DELETE|PATCH) request with the wrong CSRF token$/ do |http_method|
26
+ When /^it receives a (.*) request with the wrong CSRF token$/ do |http_method|
32
27
  begin
33
28
  @browser.request '/', :method => http_method,
34
- :params => {Rack::Csrf.csrf_field => 'whatever'}
29
+ :params => {Rack::Csrf.field => 'whatever'}
35
30
  rescue Exception => e
36
31
  @exception = e
37
32
  end
38
33
  end
39
34
 
40
- When /^it receives a (POST|PUT|DELETE|PATCH) request with neither PATH_INFO nor CSRF token$/ do |http_method|
35
+ When /^it receives a (.*) request with neither PATH_INFO nor CSRF token$/ do |http_method|
41
36
  begin
42
37
  @browser.request '/doesntmatter', :method => http_method, 'PATH_INFO' => ''
43
38
  rescue Exception => e
@@ -32,6 +32,16 @@ Given /^a rack with the anti\-CSRF middleware and the :key option$/ do
32
32
  When 'I insert the anti-CSRF middleware with the :key option'
33
33
  end
34
34
 
35
+ Given /^a rack with the anti\-CSRF middleware and the :check_also option$/ do |table|
36
+ Given 'a rack with the session middleware'
37
+ When 'I insert the anti-CSRF middleware with the :check_also option', table
38
+ end
39
+
40
+ Given /^a rack with the anti\-CSRF middleware and the :check_only option$/ do |table|
41
+ Given 'a rack with the session middleware'
42
+ When 'I insert the anti-CSRF middleware with the :check_only option', table
43
+ end
44
+
35
45
  # Yes, they're not as DRY as possible, but I think they're more readable than
36
46
  # a single step definition with a few captures and more complex checkings.
37
47
 
@@ -66,6 +76,20 @@ When /^I insert the anti\-CSRF middleware with the :key option$/ do
66
76
  @browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
67
77
  end
68
78
 
79
+ When /^I insert the anti\-CSRF middleware with the :check_also option$/ do |table|
80
+ check_also = table.hashes.collect {|t| t.values}.flatten
81
+ @rack_builder.use Rack::Csrf, :check_also => check_also
82
+ @app = toy_app
83
+ @browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
84
+ end
85
+
86
+ When /^I insert the anti\-CSRF middleware with the :check_only option$/ do |table|
87
+ must_be_checked = table.hashes.collect {|t| t.values}.flatten
88
+ @rack_builder.use Rack::Csrf, :check_only => must_be_checked
89
+ @app = toy_app
90
+ @browser = Rack::Test::Session.new(Rack::MockSession.new(@app))
91
+ end
92
+
69
93
  Then /^I get a fully functional rack$/ do
70
94
  expect {Rack::MockRequest.new(@app).get('/')}.to_not raise_exception
71
95
  end
@@ -1,12 +1,17 @@
1
1
  Feature: Customization of the field name
2
2
 
3
- Scenario: GET request with CSRF token in custom field
3
+ Background:
4
4
  Given a rack with the anti-CSRF middleware and the :field option
5
- When it receives a GET request with the CSRF token
5
+
6
+ Scenario: GET request with the right CSRF token in custom field
7
+ When it receives a GET request with the right CSRF token
8
+ Then it lets it pass untouched
9
+
10
+ Scenario: GET request with the wrong CSRF token in custom field
11
+ When it receives a GET request with the wrong CSRF token
6
12
  Then it lets it pass untouched
7
13
 
8
14
  Scenario Outline: Handling request with the right CSRF token in custom field
9
- Given a rack with the anti-CSRF middleware and the :field option
10
15
  When it receives a <method> request with the right CSRF token
11
16
  Then it lets it pass untouched
12
17
 
@@ -18,7 +23,6 @@ Feature: Customization of the field name
18
23
  | PATCH |
19
24
 
20
25
  Scenario Outline: Handling request with the wrong CSRF token in custom field
21
- Given a rack with the anti-CSRF middleware and the :field option
22
26
  When it receives a <method> request with the wrong CSRF token
23
27
  Then it responds with 403
24
28
  And the response body is empty
@@ -1,12 +1,17 @@
1
1
  Feature: Customization of the key name
2
2
 
3
- Scenario: GET request with CSRF token stored in custom key
3
+ Background:
4
4
  Given a rack with the anti-CSRF middleware and the :key option
5
- When it receives a GET request with the CSRF token
5
+
6
+ Scenario: GET request with the right CSRF token stored in custom key
7
+ When it receives a GET request with the right CSRF token
8
+ Then it lets it pass untouched
9
+
10
+ Scenario: GET request with the wrong CSRF token stored in custom key
11
+ When it receives a GET request with the wrong CSRF token
6
12
  Then it lets it pass untouched
7
13
 
8
14
  Scenario Outline: Handling request with the right CSRF token stored in custom key
9
- Given a rack with the anti-CSRF middleware and the :key option
10
15
  When it receives a <method> request with the right CSRF token
11
16
  Then it lets it pass untouched
12
17
 
@@ -18,7 +23,6 @@ Feature: Customization of the key name
18
23
  | PATCH |
19
24
 
20
25
  Scenario Outline: Handling request with the wrong CSRF token stored in custom key
21
- Given a rack with the anti-CSRF middleware and the :key option
22
26
  When it receives a <method> request with the wrong CSRF token
23
27
  Then it responds with 403
24
28
  And the response body is empty
@@ -17,22 +17,25 @@ module Rack
17
17
  @app = app
18
18
 
19
19
  @raisable = opts[:raise] || false
20
- @skippable = (opts[:skip] || []).map {|r| /\A#{r}\Z/i}
20
+ @to_be_skipped = (opts[:skip] || []).map {|r| /\A#{r}\Z/i}
21
+ @to_be_checked = (opts[:check_only] || []).map {|r| /\A#{r}\Z/i}
21
22
  @@field = opts[:field] if opts[:field]
22
23
  @@key = opts[:key] if opts[:key]
23
24
 
24
- @http_verbs = %w(POST PUT DELETE PATCH)
25
+ standard_http_methods = %w(POST PUT DELETE PATCH)
26
+ check_also = opts[:check_also] || []
27
+ @http_methods = (standard_http_methods + check_also).flatten.uniq
25
28
  end
26
29
 
27
30
  def call(env)
28
31
  unless env['rack.session']
29
32
  raise SessionUnavailable.new('Rack::Csrf depends on session middleware')
30
33
  end
31
- self.class.csrf_token(env)
34
+ self.class.token(env)
32
35
  req = Rack::Request.new(env)
33
- untouchable = !@http_verbs.include?(req.request_method) ||
34
- req.POST[self.class.csrf_field] == env['rack.session'][self.class.csrf_key] ||
35
- skip_checking(req)
36
+ untouchable = skip_checking(req) ||
37
+ !@http_methods.include?(req.request_method) ||
38
+ req.params[self.class.field] == env['rack.session'][self.class.key]
36
39
  if untouchable
37
40
  @app.call(env)
38
41
  else
@@ -41,34 +44,40 @@ module Rack
41
44
  end
42
45
  end
43
46
 
44
- def self.csrf_key
47
+ def self.key
45
48
  @@key
46
49
  end
47
50
 
48
- def self.csrf_field
51
+ def self.field
49
52
  @@field
50
53
  end
51
54
 
52
- def self.csrf_token(env)
53
- env['rack.session'][csrf_key] ||= SecureRandom.base64(32)
55
+ def self.token(env)
56
+ env['rack.session'][key] ||= SecureRandom.base64(32)
54
57
  end
55
58
 
56
- def self.csrf_tag(env)
57
- %Q(<input type="hidden" name="#{csrf_field}" value="#{csrf_token(env)}" />)
59
+ def self.tag(env)
60
+ %Q(<input type="hidden" name="#{field}" value="#{token(env)}" />)
58
61
  end
59
62
 
60
63
  class << self
61
- alias_method :key, :csrf_key
62
- alias_method :field, :csrf_field
63
- alias_method :token, :csrf_token
64
- alias_method :tag, :csrf_tag
64
+ alias_method :csrf_key, :key
65
+ alias_method :csrf_field, :field
66
+ alias_method :csrf_token, :token
67
+ alias_method :csrf_tag, :tag
65
68
  end
66
69
 
67
70
  protected
68
71
 
69
72
  def skip_checking request
73
+ skip = any? @to_be_skipped, request
74
+ allow = any? @to_be_checked, request
75
+ skip || (!@to_be_checked.empty? && !allow)
76
+ end
77
+
78
+ def any? list, request
70
79
  pi = request.path_info.empty? ? '/' : request.path_info
71
- @skippable.any? do |route|
80
+ list.any? do |route|
72
81
  route =~ (request.request_method + ':' + pi)
73
82
  end
74
83
  end
@@ -4,14 +4,14 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{rack_csrf}
8
- s.version = "2.2.0"
7
+ s.name = "rack_csrf"
8
+ s.version = "2.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Emanuele Vicentini"]
12
- s.date = %q{2011-04-12}
13
- s.description = %q{Anti-CSRF Rack middleware}
14
- s.email = %q{emanuele.vicentini@gmail.com}
12
+ s.date = "2011-10-23"
13
+ s.description = "Anti-CSRF Rack middleware"
14
+ s.email = "emanuele.vicentini@gmail.com"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.rdoc",
17
17
  "README.rdoc"
@@ -28,6 +28,14 @@ Gem::Specification.new do |s|
28
28
  "examples/camping/README.rdoc",
29
29
  "examples/camping/app.rb",
30
30
  "examples/camping/config.ru",
31
+ "examples/cuba/Gemfile",
32
+ "examples/cuba/README.rdoc",
33
+ "examples/cuba/app.rb",
34
+ "examples/cuba/config-with-raise.ru",
35
+ "examples/cuba/config.ru",
36
+ "examples/cuba/views/form.erb",
37
+ "examples/cuba/views/form_not_working.erb",
38
+ "examples/cuba/views/response.erb",
31
39
  "examples/innate/Gemfile",
32
40
  "examples/innate/README.rdoc",
33
41
  "examples/innate/app.rb",
@@ -49,7 +57,10 @@ Gem::Specification.new do |s|
49
57
  "examples/sinatra/views/form.erb",
50
58
  "examples/sinatra/views/form_not_working.erb",
51
59
  "examples/sinatra/views/response.erb",
60
+ "features/check_only_some_specific_requests.feature",
61
+ "features/custom_http_methods.feature",
52
62
  "features/empty_responses.feature",
63
+ "features/inspecting_also_get_requests.feature",
53
64
  "features/raising_exception.feature",
54
65
  "features/setup.feature",
55
66
  "features/skip_some_routes.feature",
@@ -66,13 +77,13 @@ Gem::Specification.new do |s|
66
77
  "spec/csrf_spec.rb",
67
78
  "spec/spec_helper.rb"
68
79
  ]
69
- s.homepage = %q{http://github.com/baldowl/rack_csrf}
80
+ s.homepage = "https://github.com/baldowl/rack_csrf"
70
81
  s.licenses = ["MIT"]
71
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack::Csrf 2.2.0", "--main", "README.rdoc"]
82
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack::Csrf 2.3.0", "--main", "README.rdoc"]
72
83
  s.require_paths = ["lib"]
73
- s.rubyforge_project = %q{rackcsrf}
74
- s.rubygems_version = %q{1.7.2}
75
- s.summary = %q{Anti-CSRF Rack middleware}
84
+ s.rubyforge_project = "rackcsrf"
85
+ s.rubygems_version = "1.8.11"
86
+ s.summary = "Anti-CSRF Rack middleware"
76
87
 
77
88
  if s.respond_to? :specification_version then
78
89
  s.specification_version = 3
@@ -82,17 +93,20 @@ Gem::Specification.new do |s|
82
93
  s.add_development_dependency(%q<cucumber>, [">= 0.1.13"])
83
94
  s.add_development_dependency(%q<rack-test>, [">= 0"])
84
95
  s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
96
+ s.add_development_dependency(%q<rdoc>, [">= 2.4.2"])
85
97
  else
86
98
  s.add_dependency(%q<rack>, [">= 0.9"])
87
99
  s.add_dependency(%q<cucumber>, [">= 0.1.13"])
88
100
  s.add_dependency(%q<rack-test>, [">= 0"])
89
101
  s.add_dependency(%q<rspec>, [">= 2.0.0"])
102
+ s.add_dependency(%q<rdoc>, [">= 2.4.2"])
90
103
  end
91
104
  else
92
105
  s.add_dependency(%q<rack>, [">= 0.9"])
93
106
  s.add_dependency(%q<cucumber>, [">= 0.1.13"])
94
107
  s.add_dependency(%q<rack-test>, [">= 0"])
95
108
  s.add_dependency(%q<rspec>, [">= 2.0.0"])
109
+ s.add_dependency(%q<rdoc>, [">= 2.4.2"])
96
110
  end
97
111
  end
98
112
 
@@ -1,46 +1,46 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
2
 
3
3
  describe Rack::Csrf do
4
- describe 'csrf_key' do
4
+ describe 'key' do
5
5
  it "should be 'csrf.token' by default" do
6
- Rack::Csrf.csrf_key.should == 'csrf.token'
6
+ Rack::Csrf.key.should == 'csrf.token'
7
7
  end
8
8
 
9
9
  it "should be the value of the :key option" do
10
10
  fakeapp = lambda {|env| [200, {}, []]}
11
11
  Rack::Csrf.new fakeapp, :key => 'whatever'
12
- Rack::Csrf.csrf_key.should == 'whatever'
12
+ Rack::Csrf.key.should == 'whatever'
13
13
  end
14
14
  end
15
15
 
16
- describe 'key' do
17
- it 'should be the same as csrf_key' do
18
- Rack::Csrf.method(:key).should == Rack::Csrf.method(:csrf_key)
16
+ describe 'csrf_key' do
17
+ it 'should be the same as method key' do
18
+ Rack::Csrf.method(:csrf_key).should == Rack::Csrf.method(:key)
19
19
  end
20
20
  end
21
21
 
22
- describe 'csrf_field' do
22
+ describe 'field' do
23
23
  it "should be '_csrf' by default" do
24
- Rack::Csrf.csrf_field.should == '_csrf'
24
+ Rack::Csrf.field.should == '_csrf'
25
25
  end
26
26
 
27
27
  it "should be the value of :field option" do
28
28
  fakeapp = lambda {|env| [200, {}, []]}
29
29
  Rack::Csrf.new fakeapp, :field => 'whatever'
30
- Rack::Csrf.csrf_field.should == 'whatever'
30
+ Rack::Csrf.field.should == 'whatever'
31
31
  end
32
32
  end
33
33
 
34
- describe 'field' do
35
- it 'should be the same as csrf_field' do
36
- Rack::Csrf.method(:field).should == Rack::Csrf.method(:csrf_field)
34
+ describe 'csrf_field' do
35
+ it 'should be the same as method field' do
36
+ Rack::Csrf.method(:csrf_field).should == Rack::Csrf.method(:field)
37
37
  end
38
38
  end
39
39
 
40
- describe 'csrf_token(env)' do
40
+ describe 'token(env)' do
41
41
  let(:env) { {'rack.session' => {}} }
42
42
 
43
- specify {Rack::Csrf.csrf_token(env).should have_at_least(32).characters}
43
+ specify {Rack::Csrf.token(env).should have_at_least(32).characters}
44
44
 
45
45
  context 'when accessing/manipulating the session' do
46
46
  before do
@@ -48,45 +48,45 @@ describe Rack::Csrf do
48
48
  Rack::Csrf.new fakeapp, :key => 'whatever'
49
49
  end
50
50
 
51
- it 'should use the key provided by csrf_key' do
51
+ it 'should use the key provided by method key' do
52
52
  env['rack.session'].should be_empty
53
- Rack::Csrf.csrf_token env
54
- env['rack.session'][Rack::Csrf.csrf_key].should_not be_nil
53
+ Rack::Csrf.token env
54
+ env['rack.session'][Rack::Csrf.key].should_not be_nil
55
55
  end
56
56
  end
57
57
 
58
58
  context 'when the session does not already contain the token' do
59
59
  it 'should store the token inside the session' do
60
60
  env['rack.session'].should be_empty
61
- csrf_token = Rack::Csrf.csrf_token(env)
62
- csrf_token.should == env['rack.session'][Rack::Csrf.csrf_key]
61
+ token = Rack::Csrf.token(env)
62
+ token.should == env['rack.session'][Rack::Csrf.key]
63
63
  end
64
64
  end
65
65
 
66
66
  context 'when the session already contains the token' do
67
67
  before do
68
- Rack::Csrf.csrf_token env
68
+ Rack::Csrf.token env
69
69
  end
70
70
 
71
71
  it 'should get the token from the session' do
72
- env['rack.session'][Rack::Csrf.csrf_key].should == Rack::Csrf.csrf_token(env)
72
+ env['rack.session'][Rack::Csrf.key].should == Rack::Csrf.token(env)
73
73
  end
74
74
  end
75
75
  end
76
76
 
77
- describe 'token(env)' do
78
- it 'should be the same as csrf_token(env)' do
79
- Rack::Csrf.method(:token).should == Rack::Csrf.method(:csrf_token)
77
+ describe 'csrf_token(env)' do
78
+ it 'should be the same as method token(env)' do
79
+ Rack::Csrf.method(:csrf_token).should == Rack::Csrf.method(:token)
80
80
  end
81
81
  end
82
82
 
83
- describe 'csrf_tag(env)' do
83
+ describe 'tag(env)' do
84
84
  let(:env) { {'rack.session' => {}} }
85
85
 
86
86
  let :tag do
87
87
  fakeapp = lambda {|env| [200, {}, []]}
88
88
  Rack::Csrf.new fakeapp, :field => 'whatever'
89
- Rack::Csrf.csrf_tag env
89
+ Rack::Csrf.tag env
90
90
  end
91
91
 
92
92
  it 'should be an input field' do
@@ -97,19 +97,96 @@ describe Rack::Csrf do
97
97
  tag.should =~ /type="hidden"/
98
98
  end
99
99
 
100
- it "should have the csrf_field's name" do
101
- tag.should =~ /name="#{Rack::Csrf.csrf_field}"/
100
+ it "should have the name provided by method field" do
101
+ tag.should =~ /name="#{Rack::Csrf.field}"/
102
102
  end
103
103
 
104
- it "should have the csrf_token's output" do
105
- quoted_value = Regexp.quote %Q(value="#{Rack::Csrf.csrf_token(env)}")
104
+ it "should have the value provided by method token(env)" do
105
+ quoted_value = Regexp.quote %Q(value="#{Rack::Csrf.token(env)}")
106
106
  tag.should =~ /#{quoted_value}/
107
107
  end
108
108
  end
109
109
 
110
- describe 'tag(env)' do
111
- it 'should be the same as csrf_tag(env)' do
112
- Rack::Csrf.method(:tag).should == Rack::Csrf.method(:csrf_tag)
110
+ describe 'csrf_tag(env)' do
111
+ it 'should be the same as method tag(env)' do
112
+ Rack::Csrf.method(:csrf_tag).should == Rack::Csrf.method(:tag)
113
+ end
114
+ end
115
+
116
+ describe 'skip_checking' do
117
+ class MockReq
118
+ attr_accessor :path_info, :request_method
119
+ end
120
+
121
+ before :each do
122
+ @request = MockReq.new
123
+ @request.path_info = '/hello'
124
+ @request.request_method = 'POST'
125
+ end
126
+
127
+ context 'with empty :skip and :check_only lists' do
128
+ let(:csrf) { Rack::Csrf.new nil }
129
+
130
+ it 'should run the check, irrespective of the request' do
131
+ csrf.send(:skip_checking, @request).should be_false
132
+ end
133
+ end
134
+
135
+ context 'with routes in the :skip list and nothing in the :check_only list' do
136
+ let(:csrf) { Rack::Csrf.new nil, :skip => ['POST:/hello'] }
137
+
138
+ it 'should skip the check when the request is included in the :skip list' do
139
+ csrf.send(:skip_checking, @request).should be_true
140
+ end
141
+
142
+ it 'should run the check when the request is not in the :skip list' do
143
+ @request.path_info = '/byebye'
144
+ csrf.send(:skip_checking, @request).should be_false
145
+ end
146
+ end
147
+
148
+ context 'with routes in the :check_only list and nothing in the :skip list' do
149
+ let(:csrf) { Rack::Csrf.new nil, :check_only => ['POST:/hello'] }
150
+
151
+ it 'should run the check when the request is included in the :check_only list' do
152
+ csrf.send(:skip_checking, @request).should be_false
153
+ end
154
+
155
+ it 'should skip the check when the request is not in the :check_only list' do
156
+ @request.path_info = '/byebye'
157
+ csrf.send(:skip_checking, @request).should be_true
158
+ end
159
+ end
160
+
161
+ context 'with different routes in the :skip and :check_only lists' do
162
+ let :csrf do
163
+ Rack::Csrf.new nil,
164
+ :skip => ['POST:/hello'],
165
+ :check_only => ['POST:/byebye']
166
+ end
167
+
168
+ it 'should skip the check when the request is included in the :skip list' do
169
+ csrf.send(:skip_checking, @request).should be_true
170
+ end
171
+
172
+ it 'should run the check when the request is included in the :check_only list' do
173
+ @request.path_info = '/byebye'
174
+ csrf.send(:skip_checking, @request).should be_false
175
+ end
176
+ end
177
+
178
+ context 'with the same routes in the :check_only and :skip lists' do
179
+ let :csrf do
180
+ Rack::Csrf.new nil,
181
+ :skip => ['POST:/hello'],
182
+ :check_only => ['POST:/hello']
183
+ end
184
+
185
+ context 'when the request is included in one of the list' do
186
+ it 'should ignore the :check_only list and skip the check' do
187
+ csrf.send(:skip_checking, @request).should be_true
188
+ end
189
+ end
113
190
  end
114
191
  end
115
192
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack_csrf
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 2.2.0
10
+ version: 2.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Emanuele Vicentini
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-12 00:00:00 Z
18
+ date: 2011-10-23 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rack
@@ -78,6 +78,22 @@ dependencies:
78
78
  version: 2.0.0
79
79
  type: :development
80
80
  version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ name: rdoc
83
+ prerelease: false
84
+ requirement: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 27
90
+ segments:
91
+ - 2
92
+ - 4
93
+ - 2
94
+ version: 2.4.2
95
+ type: :development
96
+ version_requirements: *id005
81
97
  description: Anti-CSRF Rack middleware
82
98
  email: emanuele.vicentini@gmail.com
83
99
  executables: []
@@ -99,6 +115,14 @@ files:
99
115
  - examples/camping/README.rdoc
100
116
  - examples/camping/app.rb
101
117
  - examples/camping/config.ru
118
+ - examples/cuba/Gemfile
119
+ - examples/cuba/README.rdoc
120
+ - examples/cuba/app.rb
121
+ - examples/cuba/config-with-raise.ru
122
+ - examples/cuba/config.ru
123
+ - examples/cuba/views/form.erb
124
+ - examples/cuba/views/form_not_working.erb
125
+ - examples/cuba/views/response.erb
102
126
  - examples/innate/Gemfile
103
127
  - examples/innate/README.rdoc
104
128
  - examples/innate/app.rb
@@ -120,7 +144,10 @@ files:
120
144
  - examples/sinatra/views/form.erb
121
145
  - examples/sinatra/views/form_not_working.erb
122
146
  - examples/sinatra/views/response.erb
147
+ - features/check_only_some_specific_requests.feature
148
+ - features/custom_http_methods.feature
123
149
  - features/empty_responses.feature
150
+ - features/inspecting_also_get_requests.feature
124
151
  - features/raising_exception.feature
125
152
  - features/setup.feature
126
153
  - features/skip_some_routes.feature
@@ -136,7 +163,7 @@ files:
136
163
  - rack_csrf.gemspec
137
164
  - spec/csrf_spec.rb
138
165
  - spec/spec_helper.rb
139
- homepage: http://github.com/baldowl/rack_csrf
166
+ homepage: https://github.com/baldowl/rack_csrf
140
167
  licenses:
141
168
  - MIT
142
169
  post_install_message:
@@ -144,7 +171,7 @@ rdoc_options:
144
171
  - --line-numbers
145
172
  - --inline-source
146
173
  - --title
147
- - Rack::Csrf 2.2.0
174
+ - Rack::Csrf 2.3.0
148
175
  - --main
149
176
  - README.rdoc
150
177
  require_paths:
@@ -170,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
197
  requirements: []
171
198
 
172
199
  rubyforge_project: rackcsrf
173
- rubygems_version: 1.7.2
200
+ rubygems_version: 1.8.11
174
201
  signing_key:
175
202
  specification_version: 3
176
203
  summary: Anti-CSRF Rack middleware