two_factor_authentication 1.1.4 → 1.1.5

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -6
  3. data/CHANGELOG.md +109 -0
  4. data/Gemfile +8 -2
  5. data/README.md +182 -54
  6. data/app/controllers/devise/two_factor_authentication_controller.rb +1 -1
  7. data/config/locales/fr.yml +7 -0
  8. data/lib/generators/active_record/templates/migration.rb +6 -11
  9. data/lib/two_factor_authentication.rb +3 -0
  10. data/lib/two_factor_authentication/hooks/two_factor_authenticatable.rb +26 -2
  11. data/lib/two_factor_authentication/models/two_factor_authenticatable.rb +89 -23
  12. data/lib/two_factor_authentication/schema.rb +12 -4
  13. data/lib/two_factor_authentication/version.rb +1 -1
  14. data/spec/controllers/two_factor_authentication_controller_spec.rb +33 -0
  15. data/spec/features/two_factor_authenticatable_spec.rb +164 -28
  16. data/spec/generators/active_record/two_factor_authentication_generator_spec.rb +36 -0
  17. data/spec/lib/two_factor_authentication/models/two_factor_authenticatable_spec.rb +213 -117
  18. data/spec/rails_app/app/models/encrypted_user.rb +14 -0
  19. data/spec/rails_app/app/models/user.rb +1 -2
  20. data/spec/rails_app/config/environments/test.rb +3 -0
  21. data/spec/rails_app/config/initializers/devise.rb +3 -1
  22. data/spec/rails_app/db/migrate/20151224171231_add_encrypted_columns_to_user.rb +9 -0
  23. data/spec/rails_app/db/migrate/20151224180310_populate_otp_column.rb +19 -0
  24. data/spec/rails_app/db/migrate/20151228230340_remove_otp_secret_key_from_user.rb +5 -0
  25. data/spec/rails_app/db/schema.rb +16 -14
  26. data/spec/spec_helper.rb +1 -0
  27. data/spec/support/authenticated_model_helper.rb +26 -2
  28. data/spec/support/controller_helper.rb +16 -0
  29. data/spec/support/features_spec_helper.rb +24 -1
  30. data/two_factor_authentication.gemspec +1 -0
  31. metadata +25 -3
  32. data/spec/controllers/two_factor_auth_spec.rb +0 -18
@@ -224,7 +224,7 @@ Devise.setup do |config|
224
224
  # config.navigational_formats = ['*/*', :html]
225
225
 
226
226
  # The default HTTP method used to sign out a resource. Default is :delete.
227
- config.sign_out_via = :delete
227
+ config.sign_out_via = Rails.env.test? ? :get : :delete
228
228
 
229
229
  # ==> OmniAuth
230
230
  # Add a new OmniAuth provider. Check the wiki for more information on setting
@@ -253,4 +253,6 @@ Devise.setup do |config|
253
253
  # When using omniauth, Devise cannot automatically set Omniauth path,
254
254
  # so you need to do it manually. For the users scope, it would be:
255
255
  # config.omniauth_path_prefix = '/my_engine/users/auth'
256
+
257
+ config.otp_secret_encryption_key = '0a8283fba984da1de24e4df1e93046cb53c5787944ef037b2dbf3e61d20fe11f25e25a855cec605fdf65b162329890d7230afdf64f681b4c32020281054e73ec'
256
258
  end
@@ -0,0 +1,9 @@
1
+ class AddEncryptedColumnsToUser < ActiveRecord::Migration
2
+ def change
3
+ add_column :users, :encrypted_otp_secret_key, :string
4
+ add_column :users, :encrypted_otp_secret_key_iv, :string
5
+ add_column :users, :encrypted_otp_secret_key_salt, :string
6
+
7
+ add_index :users, :encrypted_otp_secret_key, unique: true
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ class PopulateOtpColumn < ActiveRecord::Migration
2
+ def up
3
+ User.reset_column_information
4
+
5
+ User.find_each do |user|
6
+ user.otp_secret_key = user.read_attribute('otp_secret_key')
7
+ user.save!
8
+ end
9
+ end
10
+
11
+ def down
12
+ User.reset_column_information
13
+
14
+ User.find_each do |user|
15
+ user.otp_secret_key = ROTP::Base32.random_base32
16
+ user.save!
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ class RemoveOtpSecretKeyFromUser < ActiveRecord::Migration
2
+ def change
3
+ remove_column :users, :otp_secret_key, :string
4
+ end
5
+ end
@@ -9,30 +9,32 @@
9
9
  # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
10
  # you'll amass, the slower it'll run and the greater likelihood for issues).
11
11
  #
12
- # It's strongly recommended to check this file into your version control system.
12
+ # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20140407215513) do
14
+ ActiveRecord::Schema.define(version: 20151228230340) do
15
15
 
16
- create_table "users", :force => true do |t|
17
- t.string "email", :default => "", :null => false
18
- t.string "encrypted_password", :default => "", :null => false
16
+ create_table "users", force: :cascade do |t|
17
+ t.string "email", default: "", null: false
18
+ t.string "encrypted_password", default: "", null: false
19
19
  t.string "reset_password_token"
20
20
  t.datetime "reset_password_sent_at"
21
21
  t.datetime "remember_created_at"
22
- t.integer "sign_in_count", :default => 0, :null => false
22
+ t.integer "sign_in_count", default: 0, null: false
23
23
  t.datetime "current_sign_in_at"
24
24
  t.datetime "last_sign_in_at"
25
25
  t.string "current_sign_in_ip"
26
26
  t.string "last_sign_in_ip"
27
- t.datetime "created_at", :null => false
28
- t.datetime "updated_at", :null => false
29
- t.string "otp_secret_key"
30
- t.integer "second_factor_attempts_count", :default => 0
31
- t.string "nickname", :limit => 64
27
+ t.datetime "created_at", null: false
28
+ t.datetime "updated_at", null: false
29
+ t.integer "second_factor_attempts_count", default: 0
30
+ t.string "nickname", limit: 64
31
+ t.string "encrypted_otp_secret_key"
32
+ t.string "encrypted_otp_secret_key_iv"
33
+ t.string "encrypted_otp_secret_key_salt"
32
34
  end
33
35
 
34
- add_index "users", ["email"], :name => "index_users_on_email", :unique => true
35
- add_index "users", ["otp_secret_key"], :name => "index_users_on_otp_secret_key", :unique => true
36
- add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
36
+ add_index "users", ["email"], name: "index_users_on_email", unique: true
37
+ add_index "users", ["encrypted_otp_secret_key"], name: "index_users_on_encrypted_otp_secret_key", unique: true
38
+ add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
37
39
 
38
40
  end
@@ -3,6 +3,7 @@ require File.expand_path("../rails_app/config/environment.rb", __FILE__)
3
3
 
4
4
  require 'rspec/rails'
5
5
  require 'timecop'
6
+ require 'rack_session_access/capybara'
6
7
 
7
8
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
8
9
  RSpec.configure do |config|
@@ -1,10 +1,11 @@
1
1
  module AuthenticatedModelHelper
2
-
3
2
  def build_guest_user
4
3
  GuestUser.new
5
4
  end
6
5
 
7
- def create_user(attributes={})
6
+ def create_user(type = 'encrypted', attributes = {})
7
+ create_table_for_nonencrypted_user if type == 'not_encrypted'
8
+
8
9
  User.create!(valid_attributes(attributes))
9
10
  end
10
11
 
@@ -23,6 +24,29 @@ module AuthenticatedModelHelper
23
24
  "user#{@@email_count}@example.com"
24
25
  end
25
26
 
27
+ def create_table_for_nonencrypted_user
28
+ silence_stream(STDOUT) do
29
+ ActiveRecord::Schema.define(version: 1) do
30
+ create_table 'users', force: :cascade do |t|
31
+ t.string 'email', default: '', null: false
32
+ t.string 'encrypted_password', default: '', null: false
33
+ t.string 'reset_password_token'
34
+ t.datetime 'reset_password_sent_at'
35
+ t.datetime 'remember_created_at'
36
+ t.integer 'sign_in_count', default: 0, null: false
37
+ t.datetime 'current_sign_in_at'
38
+ t.datetime 'last_sign_in_at'
39
+ t.string 'current_sign_in_ip'
40
+ t.string 'last_sign_in_ip'
41
+ t.datetime 'created_at', null: false
42
+ t.datetime 'updated_at', null: false
43
+ t.integer 'second_factor_attempts_count', default: 0
44
+ t.string 'nickname', limit: 64
45
+ t.string 'otp_secret_key'
46
+ end
47
+ end
48
+ end
49
+ end
26
50
  end
27
51
 
28
52
  RSpec.configuration.send(:include, AuthenticatedModelHelper)
@@ -0,0 +1,16 @@
1
+ module ControllerHelper
2
+ def sign_in(user = create_user('not_encrypted'))
3
+ allow(warden).to receive(:authenticated?).with(:user).and_return(true)
4
+ allow(controller).to receive(:current_user).and_return(user)
5
+ warden.session(:user)[TwoFactorAuthentication::NEED_AUTHENTICATION] = true
6
+ end
7
+ end
8
+
9
+ RSpec.configure do |config|
10
+ config.include Devise::TestHelpers, type: :controller
11
+ config.include ControllerHelper, type: :controller
12
+
13
+ config.before(:example, type: :controller) do
14
+ @request.env['devise.mapping'] = Devise.mappings[:user]
15
+ end
16
+ end
@@ -10,10 +10,33 @@ module FeaturesSpecHelper
10
10
  fill_in "Password", with: 'password'
11
11
  find('.actions input').click # 'Sign in' or 'Log in'
12
12
  end
13
+
14
+ def set_cookie key, value
15
+ page.driver.browser.set_cookie [key, value].join('=')
16
+ end
17
+
18
+ def get_cookie key
19
+ Capybara.current_session.driver.request.cookies[key]
20
+ end
21
+
22
+ def set_tfa_cookie value
23
+ set_cookie TwoFactorAuthentication::REMEMBER_TFA_COOKIE_NAME, value
24
+ end
25
+
26
+ def get_tfa_cookie
27
+ get_cookie TwoFactorAuthentication::REMEMBER_TFA_COOKIE_NAME
28
+ end
13
29
  end
14
30
 
15
31
  RSpec.configure do |config|
16
32
  config.include Warden::Test::Helpers, type: :feature
17
33
  config.include FeaturesSpecHelper, type: :feature
18
- end
19
34
 
35
+ config.before(:each) do
36
+ Warden.test_mode!
37
+ end
38
+
39
+ config.after(:each) do
40
+ Warden.test_reset!
41
+ end
42
+ end
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_runtime_dependency 'devise'
29
29
  s.add_runtime_dependency 'randexp'
30
30
  s.add_runtime_dependency 'rotp'
31
+ s.add_runtime_dependency 'encryptor'
31
32
 
32
33
  s.add_development_dependency 'bundler'
33
34
  s.add_development_dependency 'rake'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: two_factor_authentication
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitrii Golub
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-01 00:00:00.000000000 Z
11
+ date: 2016-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: encryptor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: bundler
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +178,7 @@ extra_rdoc_files: []
164
178
  files:
165
179
  - ".gitignore"
166
180
  - ".travis.yml"
181
+ - CHANGELOG.md
167
182
  - Gemfile
168
183
  - LICENSE
169
184
  - README.md
@@ -172,6 +187,7 @@ files:
172
187
  - app/views/devise/two_factor_authentication/max_login_attempts_reached.html.erb
173
188
  - app/views/devise/two_factor_authentication/show.html.erb
174
189
  - config/locales/en.yml
190
+ - config/locales/fr.yml
175
191
  - config/locales/ru.yml
176
192
  - lib/generators/active_record/templates/migration.rb
177
193
  - lib/generators/active_record/two_factor_authentication_generator.rb
@@ -185,8 +201,9 @@ files:
185
201
  - lib/two_factor_authentication/routes.rb
186
202
  - lib/two_factor_authentication/schema.rb
187
203
  - lib/two_factor_authentication/version.rb
188
- - spec/controllers/two_factor_auth_spec.rb
204
+ - spec/controllers/two_factor_authentication_controller_spec.rb
189
205
  - spec/features/two_factor_authenticatable_spec.rb
206
+ - spec/generators/active_record/two_factor_authentication_generator_spec.rb
190
207
  - spec/lib/two_factor_authentication/models/two_factor_authenticatable_spec.rb
191
208
  - spec/rails_app/.gitignore
192
209
  - spec/rails_app/README.md
@@ -198,6 +215,7 @@ files:
198
215
  - spec/rails_app/app/helpers/application_helper.rb
199
216
  - spec/rails_app/app/mailers/.gitkeep
200
217
  - spec/rails_app/app/models/.gitkeep
218
+ - spec/rails_app/app/models/encrypted_user.rb
201
219
  - spec/rails_app/app/models/guest_user.rb
202
220
  - spec/rails_app/app/models/user.rb
203
221
  - spec/rails_app/app/views/home/dashboard.html.erb
@@ -225,6 +243,9 @@ files:
225
243
  - spec/rails_app/db/migrate/20140403184646_devise_create_users.rb
226
244
  - spec/rails_app/db/migrate/20140407172619_two_factor_authentication_add_to_users.rb
227
245
  - spec/rails_app/db/migrate/20140407215513_add_nickanme_to_users.rb
246
+ - spec/rails_app/db/migrate/20151224171231_add_encrypted_columns_to_user.rb
247
+ - spec/rails_app/db/migrate/20151224180310_populate_otp_column.rb
248
+ - spec/rails_app/db/migrate/20151228230340_remove_otp_secret_key_from_user.rb
228
249
  - spec/rails_app/db/schema.rb
229
250
  - spec/rails_app/lib/assets/.gitkeep
230
251
  - spec/rails_app/lib/sms_provider.rb
@@ -236,6 +257,7 @@ files:
236
257
  - spec/spec_helper.rb
237
258
  - spec/support/authenticated_model_helper.rb
238
259
  - spec/support/capybara.rb
260
+ - spec/support/controller_helper.rb
239
261
  - spec/support/features_spec_helper.rb
240
262
  - spec/support/sms_provider.rb
241
263
  - two_factor_authentication.gemspec
@@ -1,18 +0,0 @@
1
- require 'spec_helper'
2
-
3
- include Warden::Test::Helpers
4
-
5
- describe HomeController, :type => :controller do
6
- context "passed only 1st factor auth" do
7
- let(:user) { create_user }
8
-
9
- describe "is_fully_authenticated helper" do
10
- it "should be true" do
11
- login_as user, scope: :user
12
- visit user_two_factor_authentication_path
13
-
14
- expect(controller.is_fully_authenticated?).to be_truthy
15
- end
16
- end
17
- end
18
- end