rack_csrf 2.4.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.circleci/config.yml +30 -0
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/ci.yml +35 -0
- data/.gitignore +5 -0
- data/Changelog.md +28 -0
- data/Gemfile +2 -12
- data/LICENSE.rdoc +1 -1
- data/README.rdoc +18 -6
- data/Rakefile +11 -33
- data/examples/camping/Gemfile +2 -0
- data/examples/camping/app.rb +1 -3
- data/examples/cuba/Gemfile +1 -0
- data/examples/cuba/app.rb +2 -0
- data/examples/cuba/config-with-raise.ru +1 -2
- data/examples/cuba/config.ru +1 -2
- data/examples/innate/Gemfile +1 -0
- data/examples/innate/start-with-raise.rb +1 -3
- data/examples/innate/start.rb +1 -3
- data/examples/rack/Gemfile +2 -1
- data/examples/rack/app.rb +8 -3
- data/examples/rack/config-with-raise.ru +1 -2
- data/examples/rack/config.ru +1 -2
- data/examples/sinatra/Gemfile +2 -1
- data/examples/sinatra/app.rb +4 -2
- data/examples/sinatra/config-with-raise.ru +1 -4
- data/examples/sinatra/config.ru +1 -4
- data/features/step_definitions/request_steps.rb +7 -7
- data/features/step_definitions/response_steps.rb +5 -5
- data/features/step_definitions/setup_steps.rb +20 -14
- data/features/support/env.rb +2 -0
- data/features/support/fake_session.rb +2 -1
- data/lib/rack/csrf/version.rb +5 -0
- data/lib/rack/csrf.rb +36 -22
- data/rack_csrf.gemspec +39 -112
- data/spec/csrf_spec.rb +90 -43
- data/spec/spec_helper.rb +1 -0
- metadata +150 -142
- data/VERSION +0 -1
- data/lib/rack/vendor/securerandom.rb +0 -256
data/lib/rack/csrf.rb
CHANGED
@@ -1,12 +1,22 @@
|
|
1
|
-
require 'rack'
|
2
1
|
begin
|
3
|
-
require '
|
2
|
+
require 'rack/version'
|
4
3
|
rescue LoadError
|
5
|
-
require
|
4
|
+
require 'rack'
|
5
|
+
else
|
6
|
+
if Rack.release >= '2.3'
|
7
|
+
require 'rack/request'
|
8
|
+
require 'rack/utils'
|
9
|
+
else
|
10
|
+
require 'rack'
|
11
|
+
end
|
6
12
|
end
|
13
|
+
require 'securerandom'
|
7
14
|
|
8
15
|
module Rack
|
9
16
|
class Csrf
|
17
|
+
CONTENT_TYPE = (Rack.release >= '2.3' ? 'content-type' : 'Content-Type').freeze
|
18
|
+
CONTENT_LENGTH = (Rack.release >= '2.3' ? 'content-length' : 'Content-Length').freeze
|
19
|
+
|
10
20
|
class SessionUnavailable < StandardError; end
|
11
21
|
class InvalidCsrfToken < StandardError; end
|
12
22
|
|
@@ -17,34 +27,32 @@ module Rack
|
|
17
27
|
def initialize(app, opts = {})
|
18
28
|
@app = app
|
19
29
|
|
20
|
-
@
|
21
|
-
@skip_list
|
22
|
-
@skip_if
|
23
|
-
@check_only_list
|
24
|
-
@@field
|
25
|
-
@@header
|
26
|
-
@@key
|
30
|
+
@raise_if_invalid = opts.fetch(:raise, false)
|
31
|
+
@skip_list = opts.fetch(:skip, []).map {|r| /\A#{r}\Z/i}
|
32
|
+
@skip_if = opts[:skip_if]
|
33
|
+
@check_only_list = opts.fetch(:check_only, []).map {|r| /\A#{r}\Z/i}
|
34
|
+
@@field = opts[:field] if opts[:field]
|
35
|
+
@@header = opts[:header] if opts[:header]
|
36
|
+
@@key = opts[:key] if opts[:key]
|
27
37
|
|
28
38
|
standard_http_methods = %w(POST PUT DELETE PATCH)
|
29
|
-
check_also = opts
|
39
|
+
check_also = opts.fetch(:check_also, [])
|
30
40
|
@http_methods = (standard_http_methods + check_also).flatten.uniq
|
31
41
|
end
|
32
42
|
|
33
43
|
def call(env)
|
34
44
|
unless env['rack.session']
|
35
|
-
|
45
|
+
fail SessionUnavailable, 'Rack::Csrf depends on session middleware'
|
36
46
|
end
|
37
|
-
self.class.token(env)
|
38
47
|
req = Rack::Request.new(env)
|
39
|
-
|
48
|
+
let_it_pass = skip_checking(req) ||
|
40
49
|
!@http_methods.include?(req.request_method) ||
|
41
|
-
req
|
42
|
-
|
43
|
-
if untouchable
|
50
|
+
found_a_valid_token?(req)
|
51
|
+
if let_it_pass
|
44
52
|
@app.call(env)
|
45
53
|
else
|
46
|
-
|
47
|
-
[403, {
|
54
|
+
fail InvalidCsrfToken if @raise_if_invalid
|
55
|
+
[403, {CONTENT_TYPE => 'text/html', CONTENT_LENGTH => '0'}, []]
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
@@ -61,7 +69,7 @@ module Rack
|
|
61
69
|
end
|
62
70
|
|
63
71
|
def self.token(env)
|
64
|
-
env['rack.session'][key] ||= SecureRandom.
|
72
|
+
env['rack.session'][key] ||= SecureRandom.urlsafe_base64(32)
|
65
73
|
end
|
66
74
|
|
67
75
|
def self.tag(env)
|
@@ -69,7 +77,7 @@ module Rack
|
|
69
77
|
end
|
70
78
|
|
71
79
|
def self.metatag(env, options = {})
|
72
|
-
name = options.
|
80
|
+
name = options.fetch(:name, '_csrf')
|
73
81
|
%Q(<meta name="#{name}" content="#{token(env)}" />)
|
74
82
|
end
|
75
83
|
|
@@ -86,7 +94,7 @@ module Rack
|
|
86
94
|
|
87
95
|
# Returns the custom header's name adapted to current standards.
|
88
96
|
def self.rackified_header
|
89
|
-
"HTTP_#{@@header.gsub('-','_').upcase}"
|
97
|
+
"HTTP_#{@@header.gsub('-', '_').upcase}"
|
90
98
|
end
|
91
99
|
|
92
100
|
# Returns +true+ if the given request appears in the <b>skip list</b> or
|
@@ -108,5 +116,11 @@ module Rack
|
|
108
116
|
route =~ (request.request_method + ':' + pi)
|
109
117
|
end
|
110
118
|
end
|
119
|
+
|
120
|
+
def found_a_valid_token? request
|
121
|
+
token = self.class.token(request.env)
|
122
|
+
Rack::Utils.secure_compare(request.params[self.class.field].to_s, token) ||
|
123
|
+
Rack::Utils.secure_compare(request.env[self.class.rackified_header].to_s, token)
|
124
|
+
end
|
111
125
|
end
|
112
126
|
end
|
data/rack_csrf.gemspec
CHANGED
@@ -1,121 +1,48 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rack/csrf/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rack_csrf'
|
8
|
+
spec.version = Rack::Csrf::VERSION
|
9
|
+
spec.authors = ['Emanuele Vicentini']
|
10
|
+
spec.email = ['emanuele.vicentini@gmail.com']
|
11
|
+
spec.description = 'Anti-CSRF Rack middleware'
|
12
|
+
spec.summary = 'Anti-CSRF Rack middleware'
|
13
|
+
spec.homepage = 'https://github.com/baldowl/rack_csrf'
|
14
|
+
spec.license = 'MIT'
|
9
15
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.rdoc_options = [
|
21
|
+
'--line-numbers',
|
22
|
+
'--inline-source',
|
23
|
+
'--title',
|
24
|
+
"Rack::Csrf #{Rack::Csrf::VERSION}",
|
25
|
+
'--main',
|
26
|
+
'README.rdoc'
|
18
27
|
]
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
"Gemfile",
|
23
|
-
"LICENSE.rdoc",
|
24
|
-
"README.rdoc",
|
25
|
-
"Rakefile",
|
26
|
-
"VERSION",
|
27
|
-
"cucumber.yml",
|
28
|
-
"examples/camping/Gemfile",
|
29
|
-
"examples/camping/README.rdoc",
|
30
|
-
"examples/camping/app.rb",
|
31
|
-
"examples/camping/config.ru",
|
32
|
-
"examples/cuba/Gemfile",
|
33
|
-
"examples/cuba/README.rdoc",
|
34
|
-
"examples/cuba/app.rb",
|
35
|
-
"examples/cuba/config-with-raise.ru",
|
36
|
-
"examples/cuba/config.ru",
|
37
|
-
"examples/cuba/views/form.erb",
|
38
|
-
"examples/cuba/views/form_not_working.erb",
|
39
|
-
"examples/cuba/views/response.erb",
|
40
|
-
"examples/innate/Gemfile",
|
41
|
-
"examples/innate/README.rdoc",
|
42
|
-
"examples/innate/app.rb",
|
43
|
-
"examples/innate/start-with-raise.rb",
|
44
|
-
"examples/innate/start.rb",
|
45
|
-
"examples/innate/view/index.erb",
|
46
|
-
"examples/innate/view/notworking.erb",
|
47
|
-
"examples/innate/view/response.erb",
|
48
|
-
"examples/rack/Gemfile",
|
49
|
-
"examples/rack/README.rdoc",
|
50
|
-
"examples/rack/app.rb",
|
51
|
-
"examples/rack/config-with-raise.ru",
|
52
|
-
"examples/rack/config.ru",
|
53
|
-
"examples/sinatra/Gemfile",
|
54
|
-
"examples/sinatra/README.rdoc",
|
55
|
-
"examples/sinatra/app.rb",
|
56
|
-
"examples/sinatra/config-with-raise.ru",
|
57
|
-
"examples/sinatra/config.ru",
|
58
|
-
"examples/sinatra/views/form.erb",
|
59
|
-
"examples/sinatra/views/form_not_working.erb",
|
60
|
-
"examples/sinatra/views/response.erb",
|
61
|
-
"features/check_only_some_specific_requests.feature",
|
62
|
-
"features/custom_http_methods.feature",
|
63
|
-
"features/empty_responses.feature",
|
64
|
-
"features/inspecting_also_get_requests.feature",
|
65
|
-
"features/raising_exception.feature",
|
66
|
-
"features/setup.feature",
|
67
|
-
"features/skip_if_block_passes.feature",
|
68
|
-
"features/skip_some_routes.feature",
|
69
|
-
"features/step_definitions/request_steps.rb",
|
70
|
-
"features/step_definitions/response_steps.rb",
|
71
|
-
"features/step_definitions/setup_steps.rb",
|
72
|
-
"features/support/env.rb",
|
73
|
-
"features/support/fake_session.rb",
|
74
|
-
"features/variation_on_field_name.feature",
|
75
|
-
"features/variation_on_header_name.feature",
|
76
|
-
"features/variation_on_key_name.feature",
|
77
|
-
"lib/rack/csrf.rb",
|
78
|
-
"lib/rack/vendor/securerandom.rb",
|
79
|
-
"rack_csrf.gemspec",
|
80
|
-
"spec/csrf_spec.rb",
|
81
|
-
"spec/spec_helper.rb"
|
28
|
+
spec.extra_rdoc_files = [
|
29
|
+
'LICENSE.rdoc',
|
30
|
+
'README.rdoc'
|
82
31
|
]
|
83
|
-
s.homepage = "https://github.com/baldowl/rack_csrf"
|
84
|
-
s.licenses = ["MIT"]
|
85
|
-
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack::Csrf 2.4.0", "--main", "README.rdoc"]
|
86
|
-
s.require_paths = ["lib"]
|
87
|
-
s.rubyforge_project = "rackcsrf"
|
88
|
-
s.rubygems_version = "1.8.17"
|
89
|
-
s.summary = "Anti-CSRF Rack middleware"
|
90
32
|
|
91
|
-
|
92
|
-
s.specification_version = 3
|
33
|
+
spec.required_ruby_version = '>= 1.9.2'
|
93
34
|
|
94
|
-
|
95
|
-
|
96
|
-
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
97
|
-
s.add_development_dependency(%q<cucumber>, [">= 1.1.1"])
|
98
|
-
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
99
|
-
s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
|
100
|
-
s.add_development_dependency(%q<rdoc>, [">= 2.4.2"])
|
101
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
102
|
-
else
|
103
|
-
s.add_dependency(%q<rack>, [">= 0.9"])
|
104
|
-
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
105
|
-
s.add_dependency(%q<cucumber>, [">= 1.1.1"])
|
106
|
-
s.add_dependency(%q<rack-test>, [">= 0"])
|
107
|
-
s.add_dependency(%q<rspec>, [">= 2.0.0"])
|
108
|
-
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
109
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
110
|
-
end
|
35
|
+
if ENV['TEST_WITH_RACK']
|
36
|
+
spec.add_runtime_dependency 'rack', "~> #{ENV['TEST_WITH_RACK']}"
|
111
37
|
else
|
112
|
-
|
113
|
-
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
114
|
-
s.add_dependency(%q<cucumber>, [">= 1.1.1"])
|
115
|
-
s.add_dependency(%q<rack-test>, [">= 0"])
|
116
|
-
s.add_dependency(%q<rspec>, [">= 2.0.0"])
|
117
|
-
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
118
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
38
|
+
spec.add_runtime_dependency 'rack', '>= 1.1.0'
|
119
39
|
end
|
120
|
-
end
|
121
40
|
|
41
|
+
spec.add_development_dependency 'bundler', '>= 1.0.0'
|
42
|
+
spec.add_development_dependency 'rake'
|
43
|
+
spec.add_development_dependency 'cucumber', '~> 3.0'
|
44
|
+
spec.add_development_dependency 'rack-test', '>= 0'
|
45
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
46
|
+
spec.add_development_dependency 'rdoc', '>= 2.4.2'
|
47
|
+
spec.add_development_dependency 'git', '>= 1.2.5'
|
48
|
+
end
|
data/spec/csrf_spec.rb
CHANGED
@@ -3,58 +3,67 @@ require 'spec_helper'
|
|
3
3
|
describe Rack::Csrf do
|
4
4
|
describe 'key' do
|
5
5
|
it "should be 'csrf.token' by default" do
|
6
|
-
Rack::Csrf.key.
|
6
|
+
expect(Rack::Csrf.key).to eq('csrf.token')
|
7
7
|
end
|
8
8
|
|
9
|
-
it
|
9
|
+
it 'should be the value of the :key option' do
|
10
10
|
Rack::Csrf.new nil, :key => 'whatever'
|
11
|
-
Rack::Csrf.key.
|
11
|
+
expect(Rack::Csrf.key).to eq('whatever')
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
describe 'csrf_key' do
|
16
16
|
it 'should be the same as method key' do
|
17
|
-
Rack::Csrf.method(:csrf_key).
|
17
|
+
expect(Rack::Csrf.method(:csrf_key)).to eq(Rack::Csrf.method(:key))
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
describe 'field' do
|
22
22
|
it "should be '_csrf' by default" do
|
23
|
-
Rack::Csrf.field.
|
23
|
+
expect(Rack::Csrf.field).to eq('_csrf')
|
24
24
|
end
|
25
25
|
|
26
|
-
it
|
26
|
+
it 'should be the value of :field option' do
|
27
27
|
Rack::Csrf.new nil, :field => 'whatever'
|
28
|
-
Rack::Csrf.field.
|
28
|
+
expect(Rack::Csrf.field).to eq('whatever')
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
describe 'csrf_field' do
|
33
33
|
it 'should be the same as method field' do
|
34
|
-
Rack::Csrf.method(:csrf_field).
|
34
|
+
expect(Rack::Csrf.method(:csrf_field)).to eq(Rack::Csrf.method(:field))
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
describe 'header' do
|
39
39
|
subject { Rack::Csrf.header }
|
40
|
-
it {
|
40
|
+
it { is_expected.to be == 'X_CSRF_TOKEN' }
|
41
41
|
|
42
|
-
context
|
42
|
+
context 'when set to something' do
|
43
43
|
before { Rack::Csrf.new nil, :header => 'something' }
|
44
44
|
subject { Rack::Csrf.header }
|
45
|
-
it {
|
45
|
+
it { is_expected.to be == 'something' }
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
describe 'csrf_header' do
|
50
|
-
|
51
|
-
|
50
|
+
it 'should be the same as method header' do
|
51
|
+
expect(Rack::Csrf.method(:csrf_header)).to eq(Rack::Csrf.method(:header))
|
52
|
+
end
|
52
53
|
end
|
53
54
|
|
54
55
|
describe 'token(env)' do
|
55
56
|
let(:env) { {'rack.session' => {}} }
|
56
57
|
|
57
|
-
|
58
|
+
context 'should produce a token' do
|
59
|
+
specify 'with at least 32 characters' do
|
60
|
+
expect(Rack::Csrf.token(env).length).to be >= 32
|
61
|
+
end
|
62
|
+
|
63
|
+
specify 'without +, / or =' do
|
64
|
+
expect(Rack::Csrf.token(env)).not_to match(/\+|\/|=/)
|
65
|
+
end
|
66
|
+
end
|
58
67
|
|
59
68
|
context 'when accessing/manipulating the session' do
|
60
69
|
before do
|
@@ -62,17 +71,17 @@ describe Rack::Csrf do
|
|
62
71
|
end
|
63
72
|
|
64
73
|
it 'should use the key provided by method key' do
|
65
|
-
env['rack.session'].
|
74
|
+
expect(env['rack.session']).to be_empty
|
66
75
|
Rack::Csrf.token env
|
67
|
-
env['rack.session'][Rack::Csrf.key].
|
76
|
+
expect(env['rack.session'][Rack::Csrf.key]).not_to be_nil
|
68
77
|
end
|
69
78
|
end
|
70
79
|
|
71
80
|
context 'when the session does not already contain the token' do
|
72
81
|
it 'should store the token inside the session' do
|
73
|
-
env['rack.session'].
|
82
|
+
expect(env['rack.session']).to be_empty
|
74
83
|
token = Rack::Csrf.token(env)
|
75
|
-
token.
|
84
|
+
expect(token).to eq(env['rack.session'][Rack::Csrf.key])
|
76
85
|
end
|
77
86
|
end
|
78
87
|
|
@@ -82,14 +91,14 @@ describe Rack::Csrf do
|
|
82
91
|
end
|
83
92
|
|
84
93
|
it 'should get the token from the session' do
|
85
|
-
env['rack.session'][Rack::Csrf.key].
|
94
|
+
expect(env['rack.session'][Rack::Csrf.key]).to eq(Rack::Csrf.token(env))
|
86
95
|
end
|
87
96
|
end
|
88
97
|
end
|
89
98
|
|
90
99
|
describe 'csrf_token(env)' do
|
91
100
|
it 'should be the same as method token(env)' do
|
92
|
-
Rack::Csrf.method(:csrf_token).
|
101
|
+
expect(Rack::Csrf.method(:csrf_token)).to eq(Rack::Csrf.method(:token))
|
93
102
|
end
|
94
103
|
end
|
95
104
|
|
@@ -102,26 +111,26 @@ describe Rack::Csrf do
|
|
102
111
|
end
|
103
112
|
|
104
113
|
it 'should be an input field' do
|
105
|
-
tag.
|
114
|
+
expect(tag).to match(/^<input/)
|
106
115
|
end
|
107
116
|
|
108
117
|
it 'should be an hidden input field' do
|
109
|
-
tag.
|
118
|
+
expect(tag).to match(/type="hidden"/)
|
110
119
|
end
|
111
120
|
|
112
|
-
it
|
113
|
-
tag.
|
121
|
+
it 'should have the name provided by method field' do
|
122
|
+
expect(tag).to match(/name="#{Rack::Csrf.field}"/)
|
114
123
|
end
|
115
124
|
|
116
|
-
it
|
125
|
+
it 'should have the value provided by method token(env)' do
|
117
126
|
quoted_value = Regexp.quote %Q(value="#{Rack::Csrf.token(env)}")
|
118
|
-
tag.
|
127
|
+
expect(tag).to match(/#{quoted_value}/)
|
119
128
|
end
|
120
129
|
end
|
121
130
|
|
122
131
|
describe 'csrf_tag(env)' do
|
123
132
|
it 'should be the same as method tag(env)' do
|
124
|
-
Rack::Csrf.method(:csrf_tag).
|
133
|
+
expect(Rack::Csrf.method(:csrf_tag)).to eq(Rack::Csrf.method(:tag))
|
125
134
|
end
|
126
135
|
end
|
127
136
|
|
@@ -135,11 +144,11 @@ describe Rack::Csrf do
|
|
135
144
|
end
|
136
145
|
|
137
146
|
subject { metatag }
|
138
|
-
it {
|
139
|
-
it {
|
140
|
-
it
|
147
|
+
it { is_expected.to match(/^<meta/) }
|
148
|
+
it { is_expected.to match(/name="_csrf"/) }
|
149
|
+
it 'should have the content provided by method token(env)' do
|
141
150
|
quoted_value = Regexp.quote %Q(content="#{Rack::Csrf.token(env)}")
|
142
|
-
metatag.
|
151
|
+
expect(metatag).to match(/#{quoted_value}/)
|
143
152
|
end
|
144
153
|
end
|
145
154
|
|
@@ -150,18 +159,18 @@ describe Rack::Csrf do
|
|
150
159
|
end
|
151
160
|
|
152
161
|
subject { metatag }
|
153
|
-
it {
|
154
|
-
it {
|
155
|
-
it
|
162
|
+
it { is_expected.to match(/^<meta/) }
|
163
|
+
it { is_expected.to match(/name="custom_name"/) }
|
164
|
+
it 'should have the content provided by method token(env)' do
|
156
165
|
quoted_value = Regexp.quote %Q(content="#{Rack::Csrf.token(env)}")
|
157
|
-
metatag.
|
166
|
+
expect(metatag).to match(/#{quoted_value}/)
|
158
167
|
end
|
159
168
|
end
|
160
169
|
end
|
161
170
|
|
162
171
|
describe 'csrf_metatag(env)' do
|
163
172
|
it 'should be the same as method metatag(env)' do
|
164
|
-
Rack::Csrf.method(:csrf_metatag).
|
173
|
+
expect(Rack::Csrf.method(:csrf_metatag)).to eq(Rack::Csrf.method(:metatag))
|
165
174
|
end
|
166
175
|
end
|
167
176
|
|
@@ -170,7 +179,7 @@ describe Rack::Csrf do
|
|
170
179
|
describe 'rackified_header' do
|
171
180
|
before { Rack::Csrf.new nil, :header => 'my-header' }
|
172
181
|
subject { Rack::Csrf.rackified_header }
|
173
|
-
it {
|
182
|
+
it { is_expected.to be == 'HTTP_MY_HEADER'}
|
174
183
|
end
|
175
184
|
|
176
185
|
describe 'skip_checking' do
|
@@ -185,7 +194,7 @@ describe Rack::Csrf do
|
|
185
194
|
let(:csrf) { Rack::Csrf.new nil }
|
186
195
|
|
187
196
|
it 'should run the check' do
|
188
|
-
csrf.send(:skip_checking, request).
|
197
|
+
expect(csrf.send(:skip_checking, request)).to be false
|
189
198
|
end
|
190
199
|
end
|
191
200
|
|
@@ -193,7 +202,7 @@ describe Rack::Csrf do
|
|
193
202
|
let(:csrf) { Rack::Csrf.new nil, :skip => ['POST:/hello'] }
|
194
203
|
|
195
204
|
it 'should not run the check' do
|
196
|
-
csrf.send(:skip_checking, request).
|
205
|
+
expect(csrf.send(:skip_checking, request)).to be true
|
197
206
|
end
|
198
207
|
end
|
199
208
|
|
@@ -202,7 +211,7 @@ describe Rack::Csrf do
|
|
202
211
|
let(:csrf) { Rack::Csrf.new nil, :skip_if => lambda { |req| req.env.key?('HTTP_X_VERY_SPECIAL_HEADER') } }
|
203
212
|
|
204
213
|
it 'should not run the check' do
|
205
|
-
csrf.send(:skip_checking, request).
|
214
|
+
expect(csrf.send(:skip_checking, request)).to be true
|
206
215
|
end
|
207
216
|
end
|
208
217
|
|
@@ -211,7 +220,7 @@ describe Rack::Csrf do
|
|
211
220
|
let(:csrf) { Rack::Csrf.new nil, :check_only => [] }
|
212
221
|
|
213
222
|
it 'should run the check' do
|
214
|
-
csrf.send(:skip_checking, request).
|
223
|
+
expect(csrf.send(:skip_checking, request)).to be false
|
215
224
|
end
|
216
225
|
end
|
217
226
|
|
@@ -220,7 +229,7 @@ describe Rack::Csrf do
|
|
220
229
|
let(:csrf) { Rack::Csrf.new nil, :check_only => ['POST:/hello'] }
|
221
230
|
|
222
231
|
it 'should run the check' do
|
223
|
-
csrf.send(:skip_checking, request).
|
232
|
+
expect(csrf.send(:skip_checking, request)).to be false
|
224
233
|
end
|
225
234
|
end
|
226
235
|
|
@@ -228,11 +237,49 @@ describe Rack::Csrf do
|
|
228
237
|
let(:csrf) { Rack::Csrf.new nil, :check_only => ['POST:/ciao'] }
|
229
238
|
|
230
239
|
it 'should not run the check' do
|
231
|
-
csrf.send(:skip_checking, request).
|
240
|
+
expect(csrf.send(:skip_checking, request)).to be true
|
232
241
|
end
|
233
242
|
end
|
234
243
|
end
|
235
244
|
end
|
236
245
|
end
|
237
246
|
end
|
247
|
+
|
248
|
+
describe 'found_a_valid_token?' do
|
249
|
+
let(:env) { {'rack.session' => {}} }
|
250
|
+
|
251
|
+
let(:csrf) { Rack::Csrf.new nil }
|
252
|
+
|
253
|
+
let(:mock_request_env) do
|
254
|
+
Rack::MockRequest.env_for '/hello',
|
255
|
+
:method => 'POST',
|
256
|
+
:input => 'foo=bar'
|
257
|
+
end
|
258
|
+
|
259
|
+
before do
|
260
|
+
Rack::Csrf.token env
|
261
|
+
mock_request_env['rack.session'] = env['rack.session']
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'should be true' do
|
265
|
+
specify "if a valid token can be found in the request's paramaters" do
|
266
|
+
mock_request_env['rack.input'] = StringIO.new("#{Rack::Csrf.field}=#{Rack::Csrf.token(env)}")
|
267
|
+
request = Rack::Request.new(mock_request_env)
|
268
|
+
expect(csrf.send(:found_a_valid_token?, request)).to be true
|
269
|
+
end
|
270
|
+
|
271
|
+
specify "if a valid token can be found in the request's headers" do
|
272
|
+
mock_request_env[Rack::Csrf.rackified_header] = Rack::Csrf.token(env)
|
273
|
+
request = Rack::Request.new(mock_request_env)
|
274
|
+
expect(csrf.send(:found_a_valid_token?, request)).to be true
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
context 'should be false' do
|
279
|
+
specify 'if no valid token can be found anywhere' do
|
280
|
+
request = Rack::Request.new(mock_request_env)
|
281
|
+
expect(csrf.send(:found_a_valid_token?, request)).to be false
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
238
285
|
end
|
data/spec/spec_helper.rb
CHANGED