safe_cookies 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/safe_cookies/version.rb +1 -1
- data/lib/safe_cookies.rb +1 -1
- data/spec/safe_cookies_spec.rb +113 -0
- data/spec/spec_helper.rb +14 -0
- metadata +7 -3
data/lib/safe_cookies/version.rb
CHANGED
data/lib/safe_cookies.rb
CHANGED
@@ -100,7 +100,7 @@ module SafeCookies
|
|
100
100
|
# It contains more information than the "HTTP_COOKIE" header from the
|
101
101
|
# browser's request contained, so a `Rack::Request` can't parse it for
|
102
102
|
# us. A `Rack::Response` doesn't offer a way either.
|
103
|
-
headers['Set-Cookie'] = cookies.join("
|
103
|
+
headers['Set-Cookie'] = cookies.join("\n")
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
# Explanation:
|
5
|
+
# app#call(env) is how the middleware calls the app
|
6
|
+
# returns the app's response
|
7
|
+
# subject#call(env) is how the middleware is called "from below"
|
8
|
+
# returns the response that is passed through the web server to the client
|
9
|
+
|
10
|
+
describe SafeCookies::Middleware do
|
11
|
+
|
12
|
+
let(:app) { stub 'application' }
|
13
|
+
let(:env) { { 'HTTPS' => 'on' } }
|
14
|
+
subject { described_class.new(app) }
|
15
|
+
|
16
|
+
it 'should rewrite specified existing cookies as "secure" and "HttpOnly", but only once' do
|
17
|
+
Timecop.freeze do
|
18
|
+
# first request: rewrite cookie
|
19
|
+
subject = described_class.new(app, :foo => 24 * 60 * 60)
|
20
|
+
app.should_receive(:call).and_return([ stub, {}, stub ])
|
21
|
+
env['HTTP_COOKIE'] = 'foo=bar'
|
22
|
+
|
23
|
+
code, headers, response = subject.call(env)
|
24
|
+
expected_expiry = Rack::Utils.rfc2822((Time.now + 24 * 60 * 60).gmtime) # a special date format needed here
|
25
|
+
headers['Set-Cookie'].should =~ /foo=bar;[^\n]* HttpOnly/
|
26
|
+
headers['Set-Cookie'].should =~ /foo=bar;[^\n]* secure/
|
27
|
+
headers['Set-Cookie'].should =~ /expires=#{expected_expiry}/
|
28
|
+
headers['Set-Cookie'].should =~ /secured_old_cookies=/ # the indication cookie
|
29
|
+
|
30
|
+
# second request: do not rewrite cookie again
|
31
|
+
subject = described_class.new(app, :foo => 24 * 60 * 60)
|
32
|
+
app.should_receive(:call).and_return([ stub, {}, stub ])
|
33
|
+
received_cookies = headers['Set-Cookie'].scan(/[^,;]+=[^,;]+(?=;\s)/i) # extract cookies
|
34
|
+
env['HTTP_COOKIE'] = received_cookies.join(',')
|
35
|
+
|
36
|
+
code, headers, response = subject.call(env)
|
37
|
+
headers['Set-Cookie'].to_s.should == ""
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should make new cookies secure" do
|
42
|
+
app.should_receive(:call).and_return([ stub, { 'Set-Cookie' => 'neuer_cookie=neuer_cookie_wert'}, stub ])
|
43
|
+
|
44
|
+
code, headers, response = subject.call(env)
|
45
|
+
headers['Set-Cookie'].should =~ /neuer_cookie=neuer_cookie_wert;[^\n]* secure/
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should make new cookies http_only" do
|
49
|
+
app.should_receive(:call).and_return([ stub, { 'Set-Cookie' => 'neuer_cookie=neuer_cookie_wert'}, stub ])
|
50
|
+
|
51
|
+
code, headers, response = subject.call(env)
|
52
|
+
headers['Set-Cookie'].should =~ /neuer_cookie=neuer_cookie_wert;[^\n]* HttpOnly/
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not make new cookies secure that are specified as 'non_secure'" do
|
56
|
+
subject = described_class.new(app, :non_secure => %w[filter-settings])
|
57
|
+
app.should_receive(:call).and_return([ stub, { 'Set-Cookie' => 'filter-settings=sort_by_date'}, stub ])
|
58
|
+
|
59
|
+
code, headers, response = subject.call(env)
|
60
|
+
headers['Set-Cookie'].should include("filter-settings=sort_by_date")
|
61
|
+
headers['Set-Cookie'].should_not match(/secure/i)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not make new cookies http_only that are specified as 'non_http_only'" do
|
65
|
+
subject = described_class.new(app, :non_http_only => %w[javascript-cookie])
|
66
|
+
app.should_receive(:call).and_return([ stub, { 'Set-Cookie' => 'javascript-cookie=xss'}, stub ])
|
67
|
+
|
68
|
+
code, headers, response = subject.call(env)
|
69
|
+
headers['Set-Cookie'].should include("javascript-cookie=xss")
|
70
|
+
headers['Set-Cookie'].should_not match(/HttpOnly/i)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should prefer the application's cookie if both client and app are sending one" do
|
74
|
+
app.should_receive(:call).and_return([ stub, { 'Set-Cookie' => 'cookie=überschrieben'}, stub ])
|
75
|
+
env['HTTP_COOKIE'] = 'cookie=wert'
|
76
|
+
|
77
|
+
code, headers, response = subject.call(env)
|
78
|
+
headers['Set-Cookie'].should include("cookie=überschrieben")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should not make existing cookies secure that are specified as 'non_secure'" do
|
82
|
+
subject = described_class.new(app, :filter => 24 * 60 * 60, :non_secure => %w[filter])
|
83
|
+
app.should_receive(:call).and_return([ stub, {}, stub ])
|
84
|
+
env['HTTP_COOKIE'] = 'filter=cars_only'
|
85
|
+
|
86
|
+
code, headers, response = subject.call(env)
|
87
|
+
set_cookie = headers['Set-Cookie'].gsub(/,(?=\s\d)/, '') # remove commas in expiry dates to simplify matching below
|
88
|
+
set_cookie.should =~ /filter=cars_only;[^,]* HttpOnly/
|
89
|
+
set_cookie.should_not match(/filter=cars_only;[^,]* secure/)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should not make existing cookies http_only that are specified as 'non_http_only'" do
|
93
|
+
subject = described_class.new(app, :js_data => 24 * 60 * 60, :non_http_only => %w[js_data])
|
94
|
+
app.should_receive(:call).and_return([ stub, {}, stub ])
|
95
|
+
env['HTTP_COOKIE'] = 'js_data=json'
|
96
|
+
|
97
|
+
code, headers, response = subject.call(env)
|
98
|
+
set_cookie = headers['Set-Cookie'].gsub(/,(?=\s\d)/, '') # remove commas in expiry dates to simplify matching below
|
99
|
+
set_cookie.should =~ /js_data=json;[^,]* secure/
|
100
|
+
set_cookie.should_not match(/js_data=json;[^,]* HttpOnly/)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should not make cookies secure if the request was not secure" do
|
104
|
+
subject = described_class.new(app)
|
105
|
+
app.should_receive(:call).and_return([ stub, { 'Set-Cookie' => 'filter-settings=sort_by_date'}, stub ])
|
106
|
+
env['HTTPS'] = 'off'
|
107
|
+
|
108
|
+
code, headers, response = subject.call(env)
|
109
|
+
headers['Set-Cookie'].should include("filter-settings=sort_by_date")
|
110
|
+
headers['Set-Cookie'].should_not match(/secure/i)
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path('../../lib/safe_cookies', __FILE__)
|
2
|
+
require 'timecop'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
6
|
+
config.run_all_when_everything_filtered = true
|
7
|
+
config.filter_run :focus
|
8
|
+
|
9
|
+
# Run specs in random order to surface order dependencies. If you find an
|
10
|
+
# order dependency and want to debug it, you can fix the order by providing
|
11
|
+
# the seed, which is printed after each run.
|
12
|
+
# --seed 1234
|
13
|
+
config.order = 'random'
|
14
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe_cookies
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -74,6 +74,8 @@ files:
|
|
74
74
|
- lib/safe_cookies.rb
|
75
75
|
- lib/safe_cookies/version.rb
|
76
76
|
- safe_cookies.gemspec
|
77
|
+
- spec/safe_cookies_spec.rb
|
78
|
+
- spec/spec_helper.rb
|
77
79
|
homepage: http://www.makandra.de
|
78
80
|
licenses: []
|
79
81
|
post_install_message:
|
@@ -98,4 +100,6 @@ rubygems_version: 1.8.24
|
|
98
100
|
signing_key:
|
99
101
|
specification_version: 3
|
100
102
|
summary: Make cookies as `secure` and `HttpOnly` as possible.
|
101
|
-
test_files:
|
103
|
+
test_files:
|
104
|
+
- spec/safe_cookies_spec.rb
|
105
|
+
- spec/spec_helper.rb
|