Skip to content

Commit bc2bc75

Browse files
committed
break up cookie validations into separate methods
1 parent fa56adc commit bc2bc75

File tree

2 files changed

+71
-49
lines changed

2 files changed

+71
-49
lines changed

lib/secure_headers/headers/cookie.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class Cookie
77

88
class << self
99
def validate_config!(config)
10-
CookiesConfig.new(config).valid?
10+
CookiesConfig.new(config).validate!
1111
end
1212
end
1313

lib/secure_headers/utils/cookies_config.rb

Lines changed: 70 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,66 +7,88 @@ def initialize(config)
77
@config = config
88
end
99

10-
def valid?
11-
return if config.nil? || config == OPT_OUT
12-
raise CookiesConfigError.new("config must be a hash.") unless config.is_a? Hash
13-
14-
# secure and httponly - validate only boolean or Hash configuration
15-
[:secure, :httponly].each do |attribute|
16-
if config[attribute] && !(config[attribute].is_a?(Hash) || config[attribute].is_a?(TrueClass) || config[attribute].is_a?(FalseClass))
17-
raise CookiesConfigError.new("#{attribute} cookie config must be a hash or boolean")
18-
end
19-
end
10+
def validate!
11+
return if config.nil? || config == SecureHeaders::OPT_OUT
2012

21-
# secure and httponly - validate exclusive use of only or except but not both at the same time
22-
[:secure, :httponly].each do |attribute|
23-
if config[attribute].is_a?(Hash)
24-
if config[attribute].key?(:only) && config[attribute].key?(:except)
25-
raise CookiesConfigError.new("#{attribute} cookie config is invalid, simultaneous use of conditional arguments `only` and `except` is not permitted.")
26-
end
13+
validate_config!
14+
validate_secure_config! if config[:secure]
15+
validate_httponly_config! if config[:httponly]
16+
validate_samesite_config! if config[:samesite]
17+
end
2718

28-
if (intersection = (config[attribute].fetch(:only, []) & config[attribute].fetch(:only, []))).any?
29-
raise CookiesConfigError.new("#{attribute} cookie config is invalid, cookies #{intersection.join(', ')} cannot be enforced as lax and strict")
30-
end
31-
end
32-
end
19+
private
3320

34-
if config[:samesite]
35-
raise CookiesConfigError.new("samesite cookie config must be a hash") unless config[:samesite].is_a?(Hash)
21+
def validate_config!
22+
raise CookiesConfigError.new("config must be a hash.") unless is_hash?(config)
23+
end
3624

37-
# when configuring with booleans, only one enforcement is permitted
38-
if config[:samesite].key?(:lax) && config[:samesite][:lax].is_a?(TrueClass) && config[:samesite].key?(:strict)
39-
raise CookiesConfigError.new("samesite cookie config is invalid, combination use of booleans and Hash to configure lax and strict enforcement is not permitted.")
40-
elsif config[:samesite].key?(:strict) && config[:samesite][:strict].is_a?(TrueClass) && config[:samesite].key?(:lax)
41-
raise CookiesConfigError.new("samesite cookie config is invalid, combination use of booleans and Hash to configure lax and strict enforcement is not permitted.")
42-
end
25+
def validate_secure_config!
26+
validate_hash_or_boolean!(:secure)
27+
validate_exclusive_use_of_hash_constraints!(config[:secure], :secure)
28+
end
4329

44-
# validate Hash-based samesite configuration
45-
if config[:samesite].key?(:lax) && config[:samesite][:lax].is_a?(Hash)
46-
# validate exclusive use of only or except but not both at the same time
47-
if config[:samesite][:lax].key?(:only) && config[:samesite][:lax].key?(:except)
48-
raise CookiesConfigError.new("samesite lax cookie config is invalid, simultaneous use of conditional arguments `only` and `except` is not permitted.")
49-
end
30+
def validate_httponly_config!
31+
validate_hash_or_boolean!(:httponly)
32+
validate_exclusive_use_of_hash_constraints!(config[:httponly], :httponly)
33+
end
34+
35+
def validate_samesite_config!
36+
raise CookiesConfigError.new("samesite cookie config must be a hash") unless is_hash?(config[:samesite])
37+
38+
validate_samesite_boolean_config!
39+
validate_samesite_hash_config!
40+
end
5041

51-
if config[:samesite].key?(:strict)
52-
# validate exclusivity of only and except members
53-
if (intersection = (config[:samesite][:lax].fetch(:only, []) & config[:samesite][:strict].fetch(:only, []))).any?
54-
raise CookiesConfigError.new("samesite cookie config is invalid, cookie(s) #{intersection.join(', ')} cannot be enforced as lax and strict")
55-
end
42+
# when configuring with booleans, only one enforcement is permitted
43+
def validate_samesite_boolean_config!
44+
if config[:samesite].key?(:lax) && config[:samesite][:lax].is_a?(TrueClass) && config[:samesite].key?(:strict)
45+
raise CookiesConfigError.new("samesite cookie config is invalid, combination use of booleans and Hash to configure lax and strict enforcement is not permitted.")
46+
elsif config[:samesite].key?(:strict) && config[:samesite][:strict].is_a?(TrueClass) && config[:samesite].key?(:lax)
47+
raise CookiesConfigError.new("samesite cookie config is invalid, combination use of booleans and Hash to configure lax and strict enforcement is not permitted.")
48+
end
49+
end
5650

57-
if (intersection = (config[:samesite][:lax].fetch(:except, []) & config[:samesite][:strict].fetch(:except, []))).any?
58-
raise CookiesConfigError.new("samesite cookie config is invalid, cookie(s) #{intersection.join(', ')} cannot be enforced as lax and strict")
59-
end
51+
def validate_samesite_hash_config!
52+
# validate Hash-based samesite configuration
53+
if is_hash?(config[:samesite][:lax])
54+
validate_exclusive_use_of_hash_constraints!(config[:samesite][:lax], 'samesite lax')
55+
56+
if is_hash?(config[:samesite][:strict])
57+
validate_exclusive_use_of_hash_constraints!(config[:samesite][:strict], 'samesite strict')
58+
59+
# validate exclusivity of only and except members within strict and lax
60+
if (intersection = (config[:samesite][:lax].fetch(:only, []) & config[:samesite][:strict].fetch(:only, []))).any?
61+
raise CookiesConfigError.new("samesite cookie config is invalid, cookie(s) #{intersection.join(', ')} cannot be enforced as lax and strict")
6062
end
61-
end
6263

63-
if config[:samesite].key?(:strict) && config[:samesite][:strict].is_a?(Hash)
64-
# validate exclusive use of only or except but not both at the same time
65-
if config[:samesite][:strict].key?(:only) && config[:samesite][:strict].key?(:except)
66-
raise CookiesConfigError.new("samesite strict cookie config is invalid, simultaneous use of conditional arguments `only` and `except` is not permitted.")
64+
if (intersection = (config[:samesite][:lax].fetch(:except, []) & config[:samesite][:strict].fetch(:except, []))).any?
65+
raise CookiesConfigError.new("samesite cookie config is invalid, cookie(s) #{intersection.join(', ')} cannot be enforced as lax and strict")
6766
end
6867
end
6968
end
7069
end
70+
71+
def validate_hash_or_boolean!(attribute)
72+
if !(is_hash?(config[attribute]) || is_boolean?(config[attribute]))
73+
raise CookiesConfigError.new("#{attribute} cookie config must be a hash or boolean")
74+
end
75+
end
76+
77+
# validate exclusive use of only or except but not both at the same time
78+
def validate_exclusive_use_of_hash_constraints!(conf, attribute)
79+
return unless is_hash?(conf)
80+
81+
if conf.key?(:only) && conf.key?(:except)
82+
raise CookiesConfigError.new("#{attribute} cookie config is invalid, simultaneous use of conditional arguments `only` and `except` is not permitted.")
83+
end
84+
end
85+
86+
def is_hash?(obj)
87+
obj && obj.is_a?(Hash)
88+
end
89+
90+
def is_boolean?(obj)
91+
obj && (obj.is_a?(TrueClass) || obj.is_a?(FalseClass))
92+
end
7193
end
7294
end

0 commit comments

Comments
 (0)