safe_cookies 0.1.0 → 0.1.1
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.
- 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
|