safe_cookies 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/safe_cookies/configuration.rb +2 -1
- data/lib/safe_cookies/cookie_path_fix.rb +17 -14
- data/lib/safe_cookies/helpers.rb +96 -0
- data/lib/safe_cookies/version.rb +1 -1
- data/lib/safe_cookies.rb +55 -110
- data/safe_cookies.gemspec +1 -0
- data/spec/configuration_spec.rb +8 -31
- data/spec/safe_cookies_spec.rb +7 -4
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MjI5NWM4ZWE1M2UzNWFjNjFkNzc2M2EzN2U4NzJhZTgzNjQ0NmQ1NQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OGNlMjkzMmI2MTFhZTFlNzA3MDZmMmYxOWQ3YmQ1ZGE4Njg0OWZlOA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjU5MGUyMzQyNTI2MzE5OTkzYjBkOTI4NjQ1ZjQxOTk4NGQzOTkxMDEyNDk3
|
10
|
+
YmQ3YjJjZDBhYTU3ZjBhNzgzMGYwNzdmNzcyZTFmYWY1NzQ0N2RhZDUyYzA1
|
11
|
+
NjJlZDc4NjdiMWU2M2NhOWY5YzBmNWFkNWNmY2Y1OTgxNjI1YjQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Yjg4YTA3OGYyY2RhYmJkZTAyYmNiNjE2ZGRjNTc4MTA0NDJjMTc1ZjA3Mjcy
|
14
|
+
MjFhYjlhOGY1ZjQyYTE3OTEzODE3ZmU3YmE5YzIxOTNhOWE4NTg5M2M3ZTk4
|
15
|
+
ZWMzMzVmODk4MWE3MDdjN2RkZjI1N2UwN2EyOTVlNmM0MmMwMjk=
|
@@ -36,10 +36,11 @@ module SafeCookies
|
|
36
36
|
# :path => '/foo/path'
|
37
37
|
#
|
38
38
|
def register_cookie(name, options)
|
39
|
+
name.is_a?(String) or raise "Cookie name must be a String"
|
39
40
|
options.has_key?(:expire_after) or raise MissingOptionError.new("Cookie #{name.inspect} was registered without an expiry")
|
40
41
|
raise NotImplementedError if options.has_key?(:domain)
|
41
42
|
|
42
|
-
registered_cookies[name
|
43
|
+
registered_cookies[name] = (options || {}).freeze
|
43
44
|
insecure_cookies << name if options[:secure] == false
|
44
45
|
scriptable_cookies << name if options[:http_only] == false
|
45
46
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module SafeCookies
|
2
2
|
module CookiePathFix
|
3
|
-
|
3
|
+
|
4
4
|
# Previously, the SafeCookies gem would not set a path when rewriting
|
5
5
|
# cookies. Browsers then would assume and store the current "directory",
|
6
6
|
# leading to multiple cookies per domain.
|
@@ -10,25 +10,25 @@ module SafeCookies
|
|
10
10
|
# SECURED_COOKIE_NAME helper cookie.
|
11
11
|
# The middleware still sees the request cookies and will rewrite them as
|
12
12
|
# if it hadn't seen them before.
|
13
|
-
|
13
|
+
|
14
14
|
def fix_cookie_paths
|
15
15
|
registered_cookies_in_request.keys.each do |registered_cookie|
|
16
16
|
delete_cookie_for_current_directory(registered_cookie)
|
17
17
|
end
|
18
18
|
delete_cookie_for_current_directory(SafeCookies::SECURED_COOKIE_NAME)
|
19
|
-
|
19
|
+
|
20
20
|
# Delete this cookie here, so the middleware will secure all cookies anew.
|
21
|
-
|
21
|
+
request_cookies.delete(SafeCookies::SECURED_COOKIE_NAME)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
private
|
25
|
-
|
25
|
+
|
26
26
|
def fix_cookie_paths?
|
27
27
|
@configuration.fix_cookie_paths or return false
|
28
|
-
|
28
|
+
|
29
29
|
cookies_need_path_fix = (secured_old_cookies_timestamp < @configuration.correct_cookie_paths_timestamp)
|
30
30
|
|
31
|
-
cookies_have_been_rewritten_before and cookies_need_path_fix
|
31
|
+
cookies_have_been_rewritten_before? and cookies_need_path_fix
|
32
32
|
end
|
33
33
|
|
34
34
|
# Delete cookies by giving them an expiry in the past,
|
@@ -44,21 +44,24 @@ module SafeCookies
|
|
44
44
|
# However, Firefox includes the right-most slash when guessing the cookie path,
|
45
45
|
# so we must resort to letting browsers estimate the deletion cookie path again.
|
46
46
|
def delete_cookie_for_current_directory(cookie_name)
|
47
|
-
|
48
|
-
|
49
|
-
if current_directory_is_not_root
|
47
|
+
unless current_directory_is_root?
|
50
48
|
one_week = (7 * 24 * 60 * 60)
|
51
49
|
set_cookie!(cookie_name, "", :path => nil, :expire_after => -one_week)
|
52
50
|
end
|
53
51
|
end
|
54
|
-
|
52
|
+
|
53
|
+
def current_directory_is_root?
|
54
|
+
!@request.path[%r(^/[^/]+/[^\?]+), 0] # roughly: "there are not three slashes"
|
55
|
+
end
|
56
|
+
|
55
57
|
def secured_old_cookies_timestamp
|
56
|
-
Time.rfc2822(
|
58
|
+
Time.rfc2822(request_cookies[SafeCookies::SECURED_COOKIE_NAME])
|
57
59
|
rescue ArgumentError
|
58
60
|
# If we cannot parse the secured_old_cookies time,
|
59
61
|
# assume it was before we noticed the bug to ensure
|
60
62
|
# broken cookie paths will be fixed.
|
61
63
|
Time.parse "2013-08-25 0:00"
|
62
64
|
end
|
65
|
+
|
63
66
|
end
|
64
|
-
end
|
67
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module SafeCookies
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
KNOWN_COOKIES_DIVIDER = '|'
|
5
|
+
|
6
|
+
def cache_application_cookies_string
|
7
|
+
cookies = @headers['Set-Cookie']
|
8
|
+
# Rack 1.1 returns an Array
|
9
|
+
cookies = cookies.join("\n") if cookies.is_a?(Array)
|
10
|
+
|
11
|
+
if cookies and cookies.length > 0
|
12
|
+
@application_cookies = cookies
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def secure(cookie)
|
17
|
+
# Regexp from https://github.com/tobmatth/rack-ssl-enforcer/
|
18
|
+
if should_be_secure?(cookie) and cookie !~ /(^|;\s)secure($|;)/
|
19
|
+
"#{cookie}; secure"
|
20
|
+
else
|
21
|
+
cookie
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def http_only(cookie)
|
26
|
+
if should_be_http_only?(cookie) and cookie !~ /(^|;\s)HttpOnly($|;)/
|
27
|
+
"#{cookie}; HttpOnly"
|
28
|
+
else
|
29
|
+
cookie
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_cookie!(name, value, options)
|
34
|
+
options = options.dup
|
35
|
+
expire_after = options.delete(:expire_after)
|
36
|
+
|
37
|
+
options[:expires] = Time.now + expire_after if expire_after
|
38
|
+
options[:path] = '/' unless options.has_key?(:path) # allow setting path = nil
|
39
|
+
options[:value] = value
|
40
|
+
options[:secure] = should_be_secure?(name)
|
41
|
+
options[:httponly] = should_be_http_only?(name)
|
42
|
+
|
43
|
+
Rack::Utils.set_cookie_header!(@headers, name, options)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# getters
|
48
|
+
|
49
|
+
def stored_application_cookie_names
|
50
|
+
store_cookie = request_cookies[STORE_COOKIE_NAME] || ""
|
51
|
+
store_cookie.split(KNOWN_COOKIES_DIVIDER)
|
52
|
+
end
|
53
|
+
|
54
|
+
# returns those of the registered cookies that appear in the request
|
55
|
+
def registered_cookies_in_request
|
56
|
+
Util.slice(@configuration.registered_cookies, *request_cookies.keys)
|
57
|
+
end
|
58
|
+
|
59
|
+
def known_cookie_names
|
60
|
+
known = [STORE_COOKIE_NAME, SECURED_COOKIE_NAME]
|
61
|
+
known += stored_application_cookie_names
|
62
|
+
known += @configuration.registered_cookies.keys
|
63
|
+
end
|
64
|
+
|
65
|
+
def request_cookies
|
66
|
+
@request.cookies
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# boolean
|
71
|
+
|
72
|
+
def cookies_have_been_rewritten_before?
|
73
|
+
request_cookies.has_key? SECURED_COOKIE_NAME
|
74
|
+
end
|
75
|
+
|
76
|
+
def should_be_secure?(cookie)
|
77
|
+
cookie_name = cookie.split('=').first.strip
|
78
|
+
ssl? and not @configuration.insecure_cookie?(cookie_name)
|
79
|
+
end
|
80
|
+
|
81
|
+
def ssl?
|
82
|
+
if @request.respond_to?(:ssl?)
|
83
|
+
@request.ssl?
|
84
|
+
else
|
85
|
+
# older Rack versions
|
86
|
+
@request.scheme == 'https'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def should_be_http_only?(cookie)
|
91
|
+
cookie_name = cookie.split('=').first.strip
|
92
|
+
not @configuration.scriptable_cookie?(cookie_name)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
data/lib/safe_cookies/version.rb
CHANGED
data/lib/safe_cookies.rb
CHANGED
@@ -1,23 +1,31 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
require "safe_cookies/configuration"
|
3
3
|
require "safe_cookies/cookie_path_fix"
|
4
|
+
require "safe_cookies/helpers"
|
4
5
|
require "safe_cookies/util"
|
5
6
|
require "safe_cookies/version"
|
6
7
|
require "rack"
|
7
8
|
|
9
|
+
# Naming:
|
10
|
+
# - application_cookies: cookies received from the application. The 'Set-Cookie' header is a string
|
11
|
+
# - request_cookies: cookies received from the client. Rack::Request#cookies returns a Hash of { 'name' => 'value' }
|
12
|
+
# - response_cookies: cookies to be sent to the client
|
13
|
+
# (= application_cookies + any cookies set in the middleware)
|
14
|
+
|
8
15
|
module SafeCookies
|
9
16
|
|
10
17
|
UnknownCookieError = Class.new(StandardError)
|
11
18
|
|
12
|
-
|
19
|
+
STORE_COOKIE_NAME = '_safe_cookies__known_cookies'
|
13
20
|
SECURED_COOKIE_NAME = 'secured_old_cookies'
|
14
21
|
HELPER_COOKIES_LIFETIME = 10 * 365 * 24 * 60 * 60 # 10 years
|
15
22
|
|
16
23
|
class Middleware
|
17
24
|
|
18
25
|
include CookiePathFix
|
26
|
+
include Helpers
|
19
27
|
|
20
|
-
|
28
|
+
COOKIE_NAME_REGEX = /(?=^|\n)[^\n;,=]+/i
|
21
29
|
|
22
30
|
|
23
31
|
def initialize(app)
|
@@ -29,14 +37,16 @@ module SafeCookies
|
|
29
37
|
reset_instance_variables
|
30
38
|
|
31
39
|
@request = Rack::Request.new(env)
|
32
|
-
|
40
|
+
ensure_no_unknown_cookies_in_request!
|
33
41
|
|
34
42
|
status, @headers, body = @app.call(env)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
cache_application_cookies
|
43
|
+
cache_application_cookies_string
|
44
|
+
|
45
|
+
remove_application_cookies_from_request_cookies
|
39
46
|
rewrite_application_cookies
|
47
|
+
store_application_cookie_names
|
48
|
+
fix_cookie_paths if fix_cookie_paths?
|
49
|
+
rewrite_request_cookies unless cookies_have_been_rewritten_before?
|
40
50
|
|
41
51
|
[ status, @headers, body ]
|
42
52
|
end
|
@@ -44,63 +54,31 @@ module SafeCookies
|
|
44
54
|
private
|
45
55
|
|
46
56
|
def reset_instance_variables
|
47
|
-
@request, @headers = nil
|
57
|
+
@request, @headers, @application_cookies = nil
|
48
58
|
end
|
49
59
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
60
|
+
def ensure_no_unknown_cookies_in_request!
|
61
|
+
request_cookie_names = request_cookies.keys.map(&:to_s)
|
62
|
+
unknown_cookie_names = request_cookie_names - known_cookie_names
|
63
|
+
|
64
|
+
if unknown_cookie_names.any?
|
65
|
+
handle_unknown_cookies(unknown_cookie_names)
|
56
66
|
end
|
57
67
|
end
|
58
68
|
|
59
|
-
def
|
60
|
-
if
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# This method takes all cookies sent with the request and rewrites them,
|
68
|
-
# making them both secure and http-only (unless specified otherwise in
|
69
|
-
# the configuration).
|
70
|
-
# With the SECURED_COOKIE_NAME cookie we remember the exact time that we
|
71
|
-
# rewrote the cookies.
|
72
|
-
def rewrite_request_cookies
|
73
|
-
if @request.cookies.any?
|
74
|
-
registered_cookies_in_request.each do |registered_cookie, options|
|
75
|
-
value = @request.cookies[registered_cookie]
|
76
|
-
|
77
|
-
set_cookie!(registered_cookie, value, options)
|
69
|
+
def remove_application_cookies_from_request_cookies
|
70
|
+
if @application_cookies
|
71
|
+
application_cookie_names = @application_cookies.scan(COOKIE_NAME_REGEX)
|
72
|
+
application_cookie_names.each do |cookie|
|
73
|
+
request_cookies.delete(cookie)
|
78
74
|
end
|
79
|
-
|
80
|
-
formatted_now = Rack::Utils.rfc2822(Time.now.gmtime)
|
81
|
-
set_cookie!(SECURED_COOKIE_NAME, formatted_now, :expire_after => HELPER_COOKIES_LIFETIME)
|
82
75
|
end
|
83
76
|
end
|
84
77
|
|
85
|
-
def set_cookie!(name, value, options)
|
86
|
-
options = options.dup
|
87
|
-
expire_after = options.delete(:expire_after)
|
88
|
-
|
89
|
-
options[:expires] = Time.now + expire_after if expire_after
|
90
|
-
options[:path] = '/' unless options.has_key?(:path) # allow setting path = nil
|
91
|
-
options[:value] = value
|
92
|
-
options[:secure] = should_be_secure?(name)
|
93
|
-
options[:httponly] = should_be_http_only?(name)
|
94
|
-
|
95
|
-
Rack::Utils.set_cookie_header!(@headers, name, options)
|
96
|
-
end
|
97
|
-
|
98
78
|
def rewrite_application_cookies
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
cookies = cookies.split("\n") unless cookies.is_a?(Array)
|
103
|
-
|
79
|
+
if @application_cookies
|
80
|
+
cookies = @application_cookies.split("\n")
|
81
|
+
|
104
82
|
# On Rack 1.1, cookie values sometimes contain trailing newlines.
|
105
83
|
# Example => ["foo=1; path=/\n", "bar=2; path=/"]
|
106
84
|
# Note that they also mess up browsers, when this array is merged
|
@@ -118,69 +96,36 @@ module SafeCookies
|
|
118
96
|
@headers['Set-Cookie'] = cookies.join("\n")
|
119
97
|
end
|
120
98
|
end
|
121
|
-
|
122
|
-
def
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
if @request.respond_to?(:ssl?)
|
129
|
-
@request.ssl?
|
130
|
-
else
|
131
|
-
# older Rack versions
|
132
|
-
@request.scheme == 'https'
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def should_be_http_only?(cookie)
|
137
|
-
cookie_name = cookie.split('=').first.strip
|
138
|
-
not @configuration.scriptable_cookie?(cookie_name)
|
139
|
-
end
|
140
|
-
|
141
|
-
def ensure_no_unknown_cookies!
|
142
|
-
request_cookies = @request.cookies.keys.map(&:to_s)
|
143
|
-
unknown_cookies = request_cookies - known_cookies
|
144
|
-
|
145
|
-
if unknown_cookies.any?
|
146
|
-
handle_unknown_cookies(unknown_cookies)
|
99
|
+
|
100
|
+
def store_application_cookie_names
|
101
|
+
if @application_cookies
|
102
|
+
application_cookie_names = stored_application_cookie_names + @application_cookies.scan(COOKIE_NAME_REGEX)
|
103
|
+
application_cookies_string = application_cookie_names.uniq.join(KNOWN_COOKIES_DIVIDER)
|
104
|
+
|
105
|
+
set_cookie!(STORE_COOKIE_NAME, application_cookies_string, :expire_after => HELPER_COOKIES_LIFETIME)
|
147
106
|
end
|
148
107
|
end
|
149
108
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
109
|
+
# This method takes all cookies sent with the request and rewrites them,
|
110
|
+
# making them both secure and http-only (unless specified otherwise in
|
111
|
+
# the configuration).
|
112
|
+
# With the SECURED_COOKIE_NAME cookie we remember the exact time that we
|
113
|
+
# rewrote the cookies.
|
114
|
+
def rewrite_request_cookies
|
115
|
+
if request_cookies.any?
|
116
|
+
registered_cookies_in_request.each do |cookie_name, options|
|
117
|
+
value = request_cookies[cookie_name]
|
118
|
+
|
119
|
+
set_cookie!(cookie_name, value, options)
|
120
|
+
end
|
156
121
|
|
157
|
-
|
158
|
-
|
159
|
-
application_cookies = cached_application_cookies + new_application_cookies.scan(/(?=^|\n)[^\n;,=]+/i)
|
160
|
-
application_cookies_string = application_cookies.uniq.join(KNOWN_COOKIES_DIVIDER)
|
161
|
-
|
162
|
-
set_cookie!(CACHE_COOKIE_NAME, application_cookies_string, :expire_after => HELPER_COOKIES_LIFETIME)
|
122
|
+
formatted_now = Rack::Utils.rfc2822(Time.now.gmtime)
|
123
|
+
set_cookie!(SECURED_COOKIE_NAME, formatted_now, :expire_after => HELPER_COOKIES_LIFETIME)
|
163
124
|
end
|
164
125
|
end
|
165
126
|
|
166
|
-
def
|
167
|
-
|
168
|
-
cache_cookie.split(KNOWN_COOKIES_DIVIDER)
|
169
|
-
end
|
170
|
-
|
171
|
-
def known_cookies
|
172
|
-
known = [CACHE_COOKIE_NAME, SECURED_COOKIE_NAME]
|
173
|
-
known += cached_application_cookies
|
174
|
-
known += @configuration.registered_cookies.keys
|
175
|
-
end
|
176
|
-
|
177
|
-
def cookies_have_been_rewritten_before
|
178
|
-
@request.cookies.has_key? SECURED_COOKIE_NAME
|
179
|
-
end
|
180
|
-
|
181
|
-
# returns those of the registered cookies that appear in the request
|
182
|
-
def registered_cookies_in_request
|
183
|
-
Util.slice(@configuration.registered_cookies, *@request.cookies.keys)
|
127
|
+
def handle_unknown_cookies(cookie_names)
|
128
|
+
raise SafeCookies::UnknownCookieError.new("Request for '#{@request.url}' had unknown cookies: #{cookie_names.join(', ')}")
|
184
129
|
end
|
185
130
|
|
186
131
|
end
|
data/safe_cookies.gemspec
CHANGED
data/spec/configuration_spec.rb
CHANGED
@@ -26,53 +26,30 @@ describe SafeCookies::Middleware do
|
|
26
26
|
|
27
27
|
describe 'register_cookie' do
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
let(:set_cookie) do
|
32
|
-
# These tests for the Configuration module require an integration with
|
33
|
-
# the middleware itself. Therefore, we need to actually use it.
|
34
|
-
|
35
|
-
app = stub('app')
|
36
|
-
env = { 'HTTPS' => 'on' }
|
37
|
-
stub_app_call(app, :application_cookies => 'cookie_name=value')
|
38
|
-
|
39
|
-
middleware = described_class.new(app)
|
40
|
-
code, headers, response = middleware.call(env)
|
41
|
-
headers['Set-Cookie']
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'understands cookies registered as symbol' do
|
45
|
-
SafeCookies.configure do |config|
|
46
|
-
config.register_cookie(:cookie_name, :expire_after => nil)
|
47
|
-
end
|
48
|
-
|
49
|
-
set_cookie.should =~ /cookie_name=value;.* secure; HttpOnly/
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'understands cookies registered as string' do
|
29
|
+
it 'raises an error if a cookie is registered without passing its expiry' do
|
30
|
+
registration_without_expiry = lambda do
|
53
31
|
SafeCookies.configure do |config|
|
54
|
-
config.register_cookie('
|
32
|
+
config.register_cookie('filter', :some => :option)
|
55
33
|
end
|
56
|
-
|
57
|
-
set_cookie.should =~ /cookie_name=value;.* secure; HttpOnly/
|
58
34
|
end
|
59
35
|
|
36
|
+
expect(®istration_without_expiry).to raise_error(SafeCookies::MissingOptionError)
|
60
37
|
end
|
61
38
|
|
62
|
-
it 'raises an error if
|
63
|
-
|
39
|
+
it 'raises an error if the cookie name is not a String, because the middleware’s logic depends on strings' do
|
40
|
+
registration_as_symbol = lambda do
|
64
41
|
SafeCookies.configure do |config|
|
65
42
|
config.register_cookie(:filter, :some => :option)
|
66
43
|
end
|
67
44
|
end
|
68
45
|
|
69
|
-
expect(&
|
46
|
+
expect(®istration_as_symbol).to raise_error(RuntimeError, /must be a string/i)
|
70
47
|
end
|
71
48
|
|
72
49
|
it 'allows nil as expiry (means session cookie)' do
|
73
50
|
registration_with_nil_expiry = lambda do
|
74
51
|
SafeCookies.configure do |config|
|
75
|
-
config.register_cookie(
|
52
|
+
config.register_cookie('filter', :expire_after => nil)
|
76
53
|
end
|
77
54
|
end
|
78
55
|
|
data/spec/safe_cookies_spec.rb
CHANGED
@@ -70,7 +70,6 @@ describe SafeCookies::Middleware do
|
|
70
70
|
code, headers, response = subject.call(env)
|
71
71
|
|
72
72
|
cookies = headers['Set-Cookie'].split("\n")
|
73
|
-
cookies.size.should == 3 # my_old_cookie and secured_old_cookies and _known_cookies
|
74
73
|
cookies.each do |cookie|
|
75
74
|
cookie.should include('; path=/;')
|
76
75
|
end
|
@@ -124,7 +123,6 @@ describe SafeCookies::Middleware do
|
|
124
123
|
SafeCookies.configure do |config|
|
125
124
|
config.register_cookie('javascript-cookie', :expire_after => 3600, :http_only => false)
|
126
125
|
end
|
127
|
-
|
128
126
|
stub_app_call(app, :application_cookies => 'javascript-cookie=xss')
|
129
127
|
|
130
128
|
code, headers, response = subject.call(env)
|
@@ -132,11 +130,16 @@ describe SafeCookies::Middleware do
|
|
132
130
|
headers['Set-Cookie'].should_not =~ /javascript-cookie=.*HttpOnly/i
|
133
131
|
end
|
134
132
|
|
135
|
-
it '
|
133
|
+
it 'does not rewrite a client cookie when the application is setting a cookie with the same name' do
|
134
|
+
SafeCookies.configure do |config|
|
135
|
+
config.register_cookie('cookie', :expire_after => 3600)
|
136
|
+
end
|
137
|
+
|
136
138
|
stub_app_call(app, :application_cookies => 'cookie=from_application')
|
137
|
-
set_request_cookies(env, 'cookie=from_client
|
139
|
+
set_request_cookies(env, 'cookie=from_client')
|
138
140
|
|
139
141
|
code, headers, response = subject.call(env)
|
142
|
+
|
140
143
|
headers['Set-Cookie'].should include("cookie=from_application")
|
141
144
|
headers['Set-Cookie'].should_not include("cookie=from_client")
|
142
145
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Schöler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ! '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: debugger
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
description: Make all cookies `secure` and `HttpOnly`.
|
56
70
|
email:
|
57
71
|
- dominik.schoeler@makandra.de
|
@@ -67,6 +81,7 @@ files:
|
|
67
81
|
- lib/safe_cookies.rb
|
68
82
|
- lib/safe_cookies/configuration.rb
|
69
83
|
- lib/safe_cookies/cookie_path_fix.rb
|
84
|
+
- lib/safe_cookies/helpers.rb
|
70
85
|
- lib/safe_cookies/util.rb
|
71
86
|
- lib/safe_cookies/version.rb
|
72
87
|
- safe_cookies.gemspec
|