cookie_crypt 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cd6be403f4ffd116ee2af138abec9364b4f81a80
4
- data.tar.gz: a135e2aa98c8b52251f5d000b7f6f13120c377e7
3
+ metadata.gz: 1ab81907032931a103687c8af34b6a15ba88b053
4
+ data.tar.gz: e1394c2e8fe187f3b1363aa76cc340bc4eae0357
5
5
  SHA512:
6
- metadata.gz: fd8b49990f3a4e3692ebb9b72fc071071064fee4dd7bd444c170dda7a46f6bacaa28e5b618260394fe79eec44a0a17aab6e06d235ae2754cd65eaf0ada130cc6
7
- data.tar.gz: 834e21eb5f589775cb0b050d2e77c00e080a965a0731885d4bea9455b976b21a9674f568c499f881664f68a3ec9b8bce7883cc1c04f79e13543e8174c6ca4266
6
+ metadata.gz: cbc8b54e05d8a9aeff50f4e89493f169e4d199171f85a9a02accd7f552b2a58e0b2ae8230b894a9d5a8a5a000bf6143b80c1be9e3b75820d23f7e5d3df7eb998
7
+ data.tar.gz: 8568e107349345aa016964bad0edd7296e82818a8e7ae5ac1ff0c508f0165383d6460d34dcb0f2c4c6134d7beaa4f54d8c0f7c387fc01f60340a14c4eed1da25
data/README.md CHANGED
@@ -44,7 +44,10 @@ Run the migration with:
44
44
 
45
45
  bundle exec rake db:migrate
46
46
 
47
- With the 1.1 update, more steps are required. After following the above steps or upgrading from a previous version, run the command:
47
+ With the 1.1 update, more steps are required if you are upgrading from a previous install. If you are installing this gem for
48
+ the first time, you can disregard everything up to "Customization" as the generator will only install exactly what you need.
49
+
50
+ If you are upgrading from a previous version, run the command:
48
51
 
49
52
  bundle exec rails g cookie_crypt MODEL
50
53
 
@@ -56,6 +59,7 @@ This process will move your data (in a dev environment) from the old system to t
56
59
 
57
60
  ### Production Updating from 1.0 to 1.1
58
61
 
62
+ If you do not care about your users having to redo their questions / answers when their cookie expires, you can skip this process.
59
63
  Assuming all files are already on the production box, run
60
64
 
61
65
  bundle exec rake db:migrate VERSION=(version of the FIRST migration)
@@ -73,7 +77,7 @@ Again to remove the old fields.
73
77
 
74
78
  ### Customization
75
79
 
76
- By default encrypted cookie two factor authentication is enabled for each user, you can change it with this method in your User model:
80
+ By default encrypted cookie two factor authentication is enabled for each user, you can change it with this method in your User model (if thats what you chose to Cookie Crypt):
77
81
 
78
82
  ```ruby
79
83
  def need_two_factor_authentication?(request)
@@ -83,7 +87,45 @@ By default encrypted cookie two factor authentication is enabled for each user,
83
87
 
84
88
  This will disable two factor authentication for local users and just put the code in the logs.
85
89
 
86
- It is recommended to take a look at the source for the views, they are not complex but the default ones may not suit your design.
90
+ It is recommended to take a look at the source for the views, they are not overly complex but the default ones may not suit your design.
91
+
92
+ You can also customize options set in config/initializers/devise.rb. The default options tend to be best practices but may not suit your needs.
93
+
94
+ Question-auth refers to when a user does not have a cookie or their cookie has expired. If they have a valid cookie and user agent as described above, they will bypass
95
+ the question-auth.
96
+ * cookie_crypt_auth_through
97
+ * :one_question_cyclical
98
+ * The default
99
+ * Each user must answer only one of their questions at the end of a cookie cycle to authenticate.
100
+ * The questions are chosen cyclically, the user will not answer the same question the next time they have to question-auth through two-factor
101
+ * This prevents users logging in on a new machine from always being shown the same questions and is more secure
102
+ * :one_question_random
103
+ * The user is shown a random question that was not their previous question every time they question-auth through two-factor, otherwise exactly like cyclical
104
+ * The question asked in the previous question-auth will never be the next question-auth's question.
105
+ * :two_questions_cyclical
106
+ * Exactly like one_question_cyclical except two questions must be answered every question-auth
107
+ * :two_questions_random
108
+ * Exactly like one_question_random except two questions must be answered every question-auth
109
+ * Note: the questions will never be the same question or the FIRST question that was asked last question-auth.
110
+ * :all_questions
111
+ * This option is not advised, but is available. It is the old functionality the system had.
112
+ * The user must answer all authentication questions every question-auth session
113
+ * cookie_crypt_minimum_questions
114
+ * Default is 3
115
+ * Minimum number of questions and answers the user must enter into the system on their initial attempt
116
+ * Systems upgrading from 1.0 will prompt the user to add the difference in numbers of questions and answers
117
+ * cycle_question_on_fail_count
118
+ * Default is 2
119
+ * Minimum number of failed attempts before the question(s) is(are) cycled to the next question(s)
120
+ * enable_custom_question_counts
121
+ * Default is false
122
+ * Allows users to have more than the minimum number of security question / answer pairs. It should be noted that this enables some ajax functionality on the views page.
123
+ * max_cookie_crypt_login_attempts
124
+ * Default is 3
125
+ * The maximum number of tries a user has before they are locked out of cookie crypt and unable to fully login.
126
+ * cookie_deletion_time_frame
127
+ * Default is '30.days.from.now'
128
+ * Must be a string that evaluates to a date in the future.
87
129
 
88
130
  ### Rationalle
89
131
 
@@ -128,34 +170,4 @@ What cookie crypt doesnt prevent:
128
170
 
129
171
  Afterword: Spoofing a user agent is not that difficult, any modern browser with dev tools can change its user agent rather easily. The catch is that the values
130
172
  need to match with what the user already has which requires additional work on the attacker's part. Also, The system recognizes updates to both the user's OS AND
131
- browser.
132
-
133
-
134
- ### Whats new with the 1.1 Update
135
- * Reworked security questions and answers to allow for more customization options
136
- * cookie_crypt_auth_through
137
- * :one_question_cyclical
138
- * The default
139
- * Each user must answer only one of their questions at the end of a cookie cycle to authenticate.
140
- * The questions are chosen cyclically, the user will not answer the same question the next time they have to auth through two-factor
141
- * This prevents users logging in on a new machine from always being shown the same questions and is more secure
142
- * :one_question_random
143
- * The user is shown a random question that was not their previous question every time they auth through two-factor, otherwise exactly like cyclical
144
- * :two_questions_cyclical
145
- * Exactly like one_question_cyclical except two questions must be answered every auth
146
- * :two_questions_random
147
- * Exactly like one_question_random except two questions must be answered every auth
148
- * :all_questions
149
- * This option is not advised, but is available. It is the old functionality the system had.
150
- * The user must answer all authentication questions every auth session
151
- * cookie_crypt_minimum_questions
152
- * Default is 3
153
- * Minimum number of questions and answers the user must enter into the system on their initial attempt
154
- * Systems upgrading from 1.0 will prompt the user to add the difference in numbers of questions and answers
155
- * cycle_question_on_fail_count
156
- * Default is 2
157
- * Minimum number of failed attempts before the question(s) is(are) cycled to the next question(s)
158
- * Works in conjunction with max_cookie_crypt_login_attempts
159
- * enable_custom_question_counts
160
- * Default is false
161
- * Allows users to have more than the minimum number of security question / answer pairs.
173
+ browser. It should also be noted that cookies served over https are also further encrypted, making it much more difficult for an attacker to get the user's auth-cookie.
@@ -47,11 +47,9 @@ class Devise::CookieCryptController < DeviseController
47
47
  elsif (h.keys.count/2) < resource.class.cookie_crypt_minimum_questions # Need to update hash from an old install
48
48
 
49
49
  ((h.keys.count/2)+1..(params[:security].keys.count/2)+((h.keys.count/2))).each do |n|
50
- puts "TESTING::#{n}"
51
50
  h["security_question_#{n}"] = sanitize(params[:security]["security_question_#{n}".to_sym])
52
51
  h["security_answer_#{n}"] = Digest::SHA512.hexdigest(sanitize(params[:security]["security_answer_#{n}".to_sym]))
53
52
  end
54
- puts "TESTING2::#{h}"
55
53
  resource.security_hash = h.to_s
56
54
 
57
55
  resource.save
@@ -101,37 +99,46 @@ class Devise::CookieCryptController < DeviseController
101
99
  if resource.class.cookie_crypt_auth_through == :one_question_cyclical
102
100
  set_cyclicial_cyclemod(h)
103
101
  elsif resource.class.cookie_crypt_auth_through == :one_question_random
104
- set_random_cyclemod
102
+ set_random_cyclemod(h)
105
103
  elsif resource.class.cookie_crypt_auth_through == :two_questions_cyclical
106
104
  set_cyclicial_cyclemod(h)
107
105
 
108
106
  if session[:cyclemod]+resource.security_cycle+1 <= h.keys.count/2
109
- next_question_mod = session[:cyclemod]+1
107
+ next_question_mod = session[:cyclemod]+resource.security_cycle+1
110
108
  else
111
- next_question_mod = 0
109
+ next_question_mod = 1
112
110
  end
113
111
 
114
112
  @questions << h["security_question_#{next_question_mod}"]
115
113
  elsif resource.class.cookie_crypt_auth_through == :two_questions_random
116
114
  if resource.cookie_crypt_attempts_count == 0
117
- session[:cyclemod] = Random.rand(0..(h.keys.count/2))
118
- r = Random.rand(0..(h.keys.count/2))
119
- while session[:cyclemod] != r && resource.security_cycle != r
120
- r = Random.rand(0..(h.keys.count/2))
115
+ session[:cyclemod] ||= Random.rand(1..(h.keys.count/2))
116
+ r = Random.rand(1..(h.keys.count/2))
117
+ while session[:cyclemod] == r || resource.security_cycle == r
118
+ r = Random.rand(1..(h.keys.count/2))
121
119
  end
122
- session[:cyclemod2] = r
123
- elsif resource.cookie_crypt_attempts_count != 0 && resource.cookie_crypt_attempts_count%resource.class.cycle_question_on_fail_count == 0
124
- r = Random.rand(0..(h.keys.count/2))
125
- while session[:cyclemod] != r && resource.security_cycle != r
126
- r = Random.rand(0..(h.keys.count/2))
120
+ session[:cyclemod2] ||= r
121
+ elsif resource.cookie_crypt_attempts_count != 0 && resource.cookie_crypt_attempts_count%resource.class.cycle_question_on_fail_count == 0
122
+ #The tick assists pages that are running redirects to other sources while in two-factor mode. Without it, their
123
+ #cyclemod would desynch from the expected value on the change event (this if case) and they would be unable to auth unless the randoms matched.
124
+ session[:cookie_tick] ||= 0
125
+ session[:cookie_tick] += 1
126
+
127
+ if session[:cookie_tick] == 1
128
+ r = Random.rand(1..(h.keys.count/2))
129
+ while session[:cyclemod] == r || resource.security_cycle == r
130
+ r = Random.rand(1..(h.keys.count/2))
131
+ end
132
+ session[:cyclemod] = r
133
+
134
+ r = Random.rand(1..(h.keys.count/2))
135
+ while session[:cyclemod] == r || resource.security_cycle == r
136
+ r = Random.rand(1..(h.keys.count/2))
137
+ end
138
+ session[:cyclemod2] = r
127
139
  end
128
- session[:cyclemod] = r
129
-
130
- r = Random.rand(0..(h.keys.count/2))
131
- while session[:cyclemod] != r && resource.security_cycle != r
132
- r = Random.rand(0..(h.keys.count/2))
133
- end
134
- session[:cyclemod2] = r
140
+ else #reset the tick
141
+ session[:cookie_tick] = 0
135
142
  end
136
143
 
137
144
  @questions << h["security_question_#{session[:cyclemod2]}"]
@@ -145,6 +152,7 @@ class Devise::CookieCryptController < DeviseController
145
152
  unless resource.class.cookie_crypt_auth_through == :all_questions
146
153
  if resource.class.cookie_crypt_auth_through == :one_question_cyclical ||
147
154
  resource.class.cookie_crypt_auth_through == :two_questions_cyclical
155
+
148
156
  @questions << h["security_question_#{resource.security_cycle+session[:cyclemod]}"]
149
157
  else #random cyclemod case
150
158
  @questions << h["security_question_#{session[:cyclemod]}"]
@@ -71,6 +71,11 @@ module CookieCrypt
71
71
 
72
72
  def matching_answers? hash
73
73
  answers = []
74
+ answers_from_form = []
75
+ params[:security_answers].each_key do |key|
76
+ answers_from_form << key
77
+ end
78
+
74
79
  unless resource.class.cookie_crypt_auth_through == :all_questions
75
80
  if resource.class.cookie_crypt_auth_through == :one_question_cyclical ||
76
81
  resource.class.cookie_crypt_auth_through == :two_questions_cyclical
@@ -83,7 +88,7 @@ module CookieCrypt
83
88
 
84
89
  if resource.class.cookie_crypt_auth_through == :two_questions_cyclical
85
90
  if session[:cyclemod]+resource.security_cycle+1 <= hash.keys.count/2
86
- next_question_mod = session[:cyclemod]+1
91
+ next_question_mod = session[:cyclemod]+resource.security_cycle+1
87
92
  else
88
93
  next_question_mod = 0
89
94
  end
@@ -99,7 +104,7 @@ module CookieCrypt
99
104
 
100
105
  authed = false
101
106
  a_arr = []
102
- answers.sort.each do |key|
107
+ answers.each do |key|
103
108
  if hash[key] == Digest::SHA512.hexdigest(sanitize(params[:security_answers][key]))
104
109
  a_arr[answers.index(key)] = true
105
110
  else
@@ -123,11 +128,11 @@ module CookieCrypt
123
128
 
124
129
  def set_random_cyclemod hash
125
130
  if resource.cookie_crypt_attempts_count == 0
126
- session[:cyclemod] = Random.rand(0..(hash.keys.count/2))
131
+ session[:cyclemod] = Random.rand(1..(hash.keys.count/2))
127
132
  elsif resource.cookie_crypt_attempts_count != 0 && resource.cookie_crypt_attempts_count%resource.class.cycle_question_on_fail_count == 0
128
- r = Random.rand(0..(hash.keys.count/2))
129
- while session[:cyclemod] != r && resource.security_cycle != r
130
- r = Random.rand(0..(hash.keys.count/2))
133
+ r = Random.rand(1..(hash.keys.count/2))
134
+ while session[:cyclemod] == r || resource.security_cycle == r
135
+ r = Random.rand(1..(hash.keys.count/2))
131
136
  end
132
137
  session[:cyclemod] = r
133
138
 
@@ -135,12 +140,20 @@ module CookieCrypt
135
140
  end
136
141
 
137
142
  def update_resource_cycle hash
138
- if resource.security_cycle+1 > hash.keys.count/2
139
- resource.security_cycle = 1
140
- else
141
- resource.security_cycle += 1
142
- end
143
+ if resource.class.cookie_crypt_auth_through == :one_question_cyclical ||
144
+ resource.class.cookie_crypt_auth_through == :two_questions_cyclical
143
145
 
146
+ if resource.security_cycle+1 > hash.keys.count/2
147
+ resource.security_cycle = 1
148
+ else
149
+ resource.security_cycle += 1
150
+ end
151
+ elsif resource.class.cookie_crypt_auth_through == :one_question_random ||
152
+ resource.class.cookie_crypt_auth_through == :two_questions_random
153
+
154
+ resource.security_cycle = session[:cyclemod]
155
+ end
156
+
144
157
  resource.save
145
158
  end
146
159
 
@@ -1,3 +1,3 @@
1
1
  module CookieCrypt
2
- VERSION = "1.1.1"
2
+ VERSION = "1.1.2"
3
3
  end
@@ -5,14 +5,28 @@ module ActiveRecord
5
5
  class CookieCryptGenerator < ActiveRecord::Generators::Base
6
6
  source_root File.expand_path("../templates", __FILE__)
7
7
 
8
+ #This should only be triggered on a system that has no previous install(s)
9
+ def copy_cookie_crypt_migration_all
10
+ if ActiveRecord::Base.class_eval("#{table_name.camelize.singularize}.inspect['security_question_one: string'].blank?") &&
11
+ ActiveRecord::Base.class_eval("#{table_name.camelize.singularize}.inspect['security_hash: text'].blank?")
12
+
13
+ @ignore_other_migrations = true
14
+ migration_template "migration_complete.rb", "db/migrate/cookie_crypt_complete_install_add_to_#{table_name}"
15
+ end
16
+ end
17
+
8
18
  def copy_cookie_crypt_migration_1_0
9
- if ActiveRecord::Base.class_eval("#{table_name.camelize.singularize}.inspect['security_question_one: string'].blank?")
19
+ if ActiveRecord::Base.class_eval("#{table_name.camelize.singularize}.inspect['security_question_one: string'].blank?") &&
20
+ !@ignore_other_migrations
21
+
10
22
  migration_template "migration.rb", "db/migrate/cookie_crypt_add_to_#{table_name}"
11
23
  end
12
24
  end
13
25
 
14
26
  def copy_cookie_crypt_migration_1_1
15
- if ActiveRecord::Base.class_eval("#{table_name.camelize.singularize}.inspect['security_hash: text'].blank?")
27
+ if ActiveRecord::Base.class_eval("#{table_name.camelize.singularize}.inspect['security_hash: text'].blank?") &&
28
+ !@ignore_other_migrations
29
+
16
30
  migration_template "migration_1_1.rb", "db/migrate/cookie_crypt_1_1_update_to_#{table_name}"
17
31
  end
18
32
  end
@@ -0,0 +1,11 @@
1
+ class CookieCryptCompleteInstallAddTo<%= table_name.camelize %> < ActiveRecord::Migration
2
+ def change
3
+ change_table :<%= table_name %> do |t|
4
+ <%='t.string :username, null: false, default: ""' if ActiveRecord::Base.class_eval("#{table_name.camelize.singularize}.inspect['username: string'].blank?") %>
5
+ t.text :security_hash, default: "{}"
6
+ t.integer :security_cycle, default: 1
7
+ t.text :agent_list, default: ""
8
+ t.integer :cookie_crypt_attempts_count, default: 0
9
+ end
10
+ end
11
+ end
@@ -62,8 +62,6 @@ module CookieCryptable
62
62
  copy_file "_extra_fields.html.erb", "app/views/devise/cookie_crypt/_extra_fields.html.erb"
63
63
  File.delete("app/views/devise/cookie_crypt/show.html.erb")
64
64
  copy_file "show.html.erb", "app/views/devise/cookie_crypt/show.html.erb"
65
-
66
- puts "Please run rake db:migrate then run this generator again to cleanup unused fields."
67
65
  end
68
66
  end
69
67
 
@@ -82,8 +80,6 @@ module CookieCryptable
82
80
  obj.security_hash = h.to_s
83
81
 
84
82
  obj.save
85
-
86
- puts "#{obj.security_hash}"
87
83
  end
88
84
 
89
85
  puts "Completed data cleanup, database is now 1.1 ready."
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cookie_crypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitrii Golub
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-21 00:00:00.000000000 Z
12
+ date: 2013-11-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -103,6 +103,7 @@ files:
103
103
  - lib/generators/active_record/templates/migration.rb
104
104
  - lib/generators/active_record/templates/migration_1_1.rb
105
105
  - lib/generators/active_record/templates/migration_1_1_cleanup.rb
106
+ - lib/generators/active_record/templates/migration_complete.rb
106
107
  - lib/generators/cookie_crypt/cookie_crypt_generator.rb
107
108
  homepage: https://github.com/loualrid/CookieCrypt
108
109
  licenses: