devise-multi-factor 3.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +21 -0
  3. data/.github/workflows/gem-push.yml +42 -0
  4. data/.gitignore +23 -0
  5. data/.rubocop.yml +295 -0
  6. data/.travis.yml +28 -0
  7. data/CHANGELOG.md +119 -0
  8. data/Gemfile +32 -0
  9. data/LICENSE +19 -0
  10. data/README.md +322 -0
  11. data/Rakefile +12 -0
  12. data/app/controllers/devise/totp_controller.rb +79 -0
  13. data/app/controllers/devise/two_factor_authentication_controller.rb +84 -0
  14. data/app/views/devise/two_factor_authentication/max_login_attempts_reached.html.erb +3 -0
  15. data/app/views/devise/two_factor_authentication/new.html.erb +14 -0
  16. data/app/views/devise/two_factor_authentication/show.html.erb +19 -0
  17. data/config/locales/de.yml +8 -0
  18. data/config/locales/en.yml +8 -0
  19. data/config/locales/es.yml +8 -0
  20. data/config/locales/fr.yml +8 -0
  21. data/config/locales/ru.yml +8 -0
  22. data/devise-multi-factor.gemspec +40 -0
  23. data/lib/devise-multi-factor.rb +1 -0
  24. data/lib/devise_multi_factor.rb +56 -0
  25. data/lib/devise_multi_factor/controllers/helpers.rb +57 -0
  26. data/lib/devise_multi_factor/hooks/two_factor_authenticatable.rb +17 -0
  27. data/lib/devise_multi_factor/models/totp_enrollable.rb +7 -0
  28. data/lib/devise_multi_factor/models/two_factor_authenticatable.rb +142 -0
  29. data/lib/devise_multi_factor/orm/active_record.rb +14 -0
  30. data/lib/devise_multi_factor/rails.rb +7 -0
  31. data/lib/devise_multi_factor/routes.rb +15 -0
  32. data/lib/devise_multi_factor/schema.rb +23 -0
  33. data/lib/devise_multi_factor/version.rb +3 -0
  34. data/lib/generators/active_record/devise_multi_factor_generator.rb +13 -0
  35. data/lib/generators/active_record/templates/migration.rb +11 -0
  36. data/lib/generators/devise_multi_factor/devise_multi_factor_generator.rb +17 -0
  37. data/spec/controllers/two_factor_authentication_controller_spec.rb +41 -0
  38. data/spec/features/two_factor_authenticatable_spec.rb +237 -0
  39. data/spec/generators/active_record/devise_multi_factor_generator_spec.rb +34 -0
  40. data/spec/lib/devise_multi_factor/models/two_factor_authenticatable_spec.rb +282 -0
  41. data/spec/rails_app/.gitignore +3 -0
  42. data/spec/rails_app/README.md +3 -0
  43. data/spec/rails_app/Rakefile +7 -0
  44. data/spec/rails_app/app/assets/config/manifest.js +2 -0
  45. data/spec/rails_app/app/assets/javascripts/application.js +1 -0
  46. data/spec/rails_app/app/assets/stylesheets/application.css +4 -0
  47. data/spec/rails_app/app/controllers/application_controller.rb +3 -0
  48. data/spec/rails_app/app/controllers/home_controller.rb +10 -0
  49. data/spec/rails_app/app/helpers/application_helper.rb +8 -0
  50. data/spec/rails_app/app/mailers/.gitkeep +0 -0
  51. data/spec/rails_app/app/models/.gitkeep +0 -0
  52. data/spec/rails_app/app/models/admin.rb +6 -0
  53. data/spec/rails_app/app/models/encrypted_user.rb +7 -0
  54. data/spec/rails_app/app/models/guest_user.rb +7 -0
  55. data/spec/rails_app/app/models/test_user.rb +38 -0
  56. data/spec/rails_app/app/models/user.rb +18 -0
  57. data/spec/rails_app/app/views/home/dashboard.html.erb +11 -0
  58. data/spec/rails_app/app/views/home/index.html.erb +3 -0
  59. data/spec/rails_app/app/views/layouts/application.html.erb +20 -0
  60. data/spec/rails_app/config.ru +4 -0
  61. data/spec/rails_app/config/application.rb +61 -0
  62. data/spec/rails_app/config/boot.rb +10 -0
  63. data/spec/rails_app/config/database.yml +19 -0
  64. data/spec/rails_app/config/environment.rb +5 -0
  65. data/spec/rails_app/config/environments/development.rb +28 -0
  66. data/spec/rails_app/config/environments/production.rb +68 -0
  67. data/spec/rails_app/config/environments/test.rb +41 -0
  68. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  69. data/spec/rails_app/config/initializers/cookies_serializer.rb +3 -0
  70. data/spec/rails_app/config/initializers/devise.rb +258 -0
  71. data/spec/rails_app/config/initializers/inflections.rb +15 -0
  72. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  73. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  74. data/spec/rails_app/config/initializers/session_store.rb +8 -0
  75. data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
  76. data/spec/rails_app/config/locales/devise.en.yml +59 -0
  77. data/spec/rails_app/config/locales/en.yml +5 -0
  78. data/spec/rails_app/config/routes.rb +65 -0
  79. data/spec/rails_app/db/migrate/20140403184646_devise_create_users.rb +42 -0
  80. data/spec/rails_app/db/migrate/20140407172619_two_factor_authentication_add_to_users.rb +17 -0
  81. data/spec/rails_app/db/migrate/20140407215513_add_nickanme_to_users.rb +7 -0
  82. data/spec/rails_app/db/migrate/20151224171231_add_encrypted_columns_to_user.rb +7 -0
  83. data/spec/rails_app/db/migrate/20151224180310_populate_otp_column.rb +19 -0
  84. data/spec/rails_app/db/migrate/20151228230340_remove_otp_secret_key_from_user.rb +5 -0
  85. data/spec/rails_app/db/migrate/20160209032439_devise_create_admins.rb +42 -0
  86. data/spec/rails_app/db/schema.rb +55 -0
  87. data/spec/rails_app/lib/assets/.gitkeep +0 -0
  88. data/spec/rails_app/lib/sms_provider.rb +17 -0
  89. data/spec/rails_app/public/404.html +26 -0
  90. data/spec/rails_app/public/422.html +26 -0
  91. data/spec/rails_app/public/500.html +25 -0
  92. data/spec/rails_app/public/favicon.ico +0 -0
  93. data/spec/rails_app/script/rails +6 -0
  94. data/spec/spec_helper.rb +26 -0
  95. data/spec/support/authenticated_model_helper.rb +29 -0
  96. data/spec/support/capybara.rb +3 -0
  97. data/spec/support/controller_helper.rb +16 -0
  98. data/spec/support/features_spec_helper.rb +42 -0
  99. data/spec/support/sms_provider.rb +5 -0
  100. data/spec/support/totp_helper.rb +11 -0
  101. metadata +315 -0
data/Gemfile ADDED
@@ -0,0 +1,32 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in devise_ip_filter.gemspec
4
+ gemspec
5
+
6
+ rails_version = ENV["RAILS_VERSION"] || "default"
7
+
8
+ rails = case rails_version
9
+ when "master"
10
+ {github: "rails/rails"}
11
+ when "default"
12
+ "~> 5.2"
13
+ else
14
+ "~> #{rails_version}"
15
+ end
16
+
17
+ gem "rails", rails
18
+
19
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.2.0')
20
+ gem "test-unit", "~> 3.0"
21
+ end
22
+
23
+ group :test, :development do
24
+ gem 'byebug'
25
+ gem 'lockbox'
26
+ gem 'sqlite3'
27
+ end
28
+
29
+ group :test do
30
+ gem 'rack_session_access'
31
+ gem 'ammeter'
32
+ end
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2012 Dmitrii Golub
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,322 @@
1
+ # Devise Multi Factor
2
+
3
+ This is a fork of the gem [two_factor_authentication](https://github.com/Houdini/two_factor_authentication) by Houdini. The name has been changed to `devise-multi-factor` to avoid conflicts of both gems.
4
+ This version uses [Lockbox](https://github.com/ankane/lockbox) to manage the encryption of the key.
5
+
6
+ ## Features
7
+
8
+ * Support for 2 types of OTP codes
9
+ 1. Codes delivered directly to the user
10
+ 2. TOTP (Google Authenticator) codes based on a shared secret (HMAC)
11
+ * Configurable OTP code digit length
12
+ * Configurable max login attempts
13
+ * Customizable logic to determine if a user needs two factor authentication
14
+ * Configurable period where users won't be asked for 2FA again
15
+ * TOTP secret key automatically encrypted in DB
16
+ * Enroll form for TOTP using `:totp_enrollable` on your model
17
+
18
+ ## Configuration
19
+
20
+ ### Initial Setup
21
+
22
+ In a Rails environment, require the gem in your Gemfile:
23
+
24
+ gem 'devise-multi-factor'
25
+
26
+ Once that's done, run:
27
+
28
+ bundle install
29
+
30
+ Note that Ruby 2.1 or greater is required.
31
+
32
+ ### Installation
33
+
34
+ #### Automatic initial setup
35
+
36
+ To set up the model and database migration file automatically, run the
37
+ following command:
38
+
39
+ bundle exec rails g devise_multi_factor MODEL
40
+
41
+ Where MODEL is your model name (e.g. User or Admin). This generator will add
42
+ `:two_factor_authenticatable` to your model's Devise options and create a
43
+ migration in `db/migrate/`, which will add the following columns to your table:
44
+
45
+ - `:second_factor_attempts_count`
46
+ - `:encrypted_otp_secret_key`
47
+ - `:direct_otp`
48
+ - `:direct_otp_sent_at`
49
+ - `:totp_timestamp`
50
+
51
+ #### Manual initial setup
52
+
53
+ If you prefer to set up the model and migration manually, add the
54
+ `:two_factor_authenticatable` option to your existing devise options, such as:
55
+
56
+ ```ruby
57
+ devise :database_authenticatable, :registerable, :recoverable, :rememberable,
58
+ :trackable, :validatable, :two_factor_authenticatable
59
+ ```
60
+
61
+ Then create your migration file using the Rails generator, such as:
62
+
63
+ ```
64
+ rails g migration AddTwoFactorFieldsToUsers second_factor_attempts_count:integer encrypted_otp_secret_key:string direct_otp:string direct_otp_sent_at:datetime totp_timestamp:integer
65
+ ```
66
+
67
+ #### Complete the setup
68
+
69
+ Run the migration with:
70
+
71
+ bundle exec rake db:migrate
72
+
73
+ Add the following line to your model to fully enable two-factor auth:
74
+
75
+ has_one_time_password
76
+
77
+ Set config values in `config/initializers/devise.rb`:
78
+
79
+ ```ruby
80
+ config.max_login_attempts = 3 # Maximum second factor attempts count.
81
+ config.allowed_otp_drift_seconds = 30 # Allowed TOTP time drift between client and server.
82
+ config.otp_length = 6 # TOTP code length
83
+ config.direct_otp_valid_for = 5.minutes # Time before direct OTP becomes invalid
84
+ config.direct_otp_length = 6 # Direct OTP code length
85
+ config.remember_otp_session_for_seconds = 30.days # Time before browser has to perform 2fA again. Default is 0.
86
+ config.otp_secret_encryption_key = ENV['OTP_SECRET_ENCRYPTION_KEY']
87
+ config.second_factor_resource_id = 'id' # Field or method name used to set value for 2fA remember cookie
88
+ config.delete_cookie_on_logout = false # Delete cookie when user signs out, to force 2fA again on login
89
+ ```
90
+ The `otp_secret_encryption_key` must be a random key that is not stored in the
91
+ DB, and is not checked in to your repo. It is recommended to store it in an
92
+ environment variable, and you can generate it with `bundle exec rake secret`.
93
+
94
+ Override the method in your model in order to send direct OTP codes. This is
95
+ automatically called when a user logs in unless they have TOTP enabled (see
96
+ below):
97
+
98
+ ```ruby
99
+ def send_two_factor_authentication_code(code)
100
+ # Send code via SMS, etc.
101
+ end
102
+ ```
103
+
104
+ ### Customisation and Usage
105
+
106
+ By default, second factor authentication is required for each user. You can
107
+ change that by overriding the following method in your model:
108
+
109
+ ```ruby
110
+ def need_two_factor_authentication?(request)
111
+ request.ip != '127.0.0.1'
112
+ end
113
+ ```
114
+
115
+ In the example above, two factor authentication will not be required for local
116
+ users.
117
+
118
+ This gem is compatible with [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en).
119
+ To enable this a shared secret must be generated by invoking the following
120
+ method on your model:
121
+
122
+ ```ruby
123
+ user.generate_totp_secret
124
+ ```
125
+
126
+ This must then be shared via a provisioning uri:
127
+
128
+ ```ruby
129
+ user.provisioning_uri # This assumes a user model with an email attribute
130
+ ```
131
+
132
+ This provisioning uri can then be turned in to a QR code if desired so that
133
+ users may add the app to Google Authenticator easily. Once this is done, they
134
+ may retrieve a one-time password directly from the Google Authenticator app.
135
+
136
+ #### Overriding the view
137
+
138
+ The default view that shows the form can be overridden by adding a
139
+ file named `show.html.erb` (or `show.html.haml` if you prefer HAML)
140
+ inside `app/views/devise/two_factor_authentication/` and customizing it.
141
+ Below is an example using ERB:
142
+
143
+
144
+ ```html
145
+ <h2>Hi, you received a code by email, please enter it below, thanks!</h2>
146
+
147
+ <%= form_tag([resource_name, :two_factor_authentication], :method => :put) do %>
148
+ <%= text_field_tag :code %>
149
+ <%= submit_tag "Log in!" %>
150
+ <% end %>
151
+
152
+ <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
153
+ ```
154
+
155
+ #### Upgrading from version 1.X to 2.X
156
+
157
+ The following database fields are new in version 2.
158
+
159
+ - `direct_otp`
160
+ - `direct_otp_sent_at`
161
+ - `totp_timestamp`
162
+
163
+ To add them, generate a migration such as:
164
+
165
+ $ rails g migration AddTwoFactorFieldsToUsers direct_otp:string direct_otp_sent_at:datetime totp_timestamp:timestamp
166
+
167
+ The `otp_secret_key` is only required for users who use TOTP (Google Authenticator) codes,
168
+ so unless it has been shared with the user it should be set to `nil`. The
169
+ following pseudo-code is an example of how this might be done:
170
+
171
+ ```ruby
172
+ User.find_each do |user| do
173
+ if !uses_authenticator_app(user)
174
+ user.otp_secret_key = nil
175
+ user.save!
176
+ end
177
+ end
178
+ ```
179
+
180
+ #### Adding the TOTP encryption option to an existing app
181
+
182
+ If you've already been using this gem, and want to start encrypting the OTP
183
+ secret key in the database (recommended), you'll need to perform the following
184
+ steps:
185
+
186
+ 1. Generate a migration to add the necessary columns to your model's table:
187
+
188
+ ```
189
+ rails g migration AddEncryptionFieldsToUsers encrypted_otp_secret_key:string
190
+ ```
191
+
192
+ Open your migration file (it will be in the `db/migrate` directory and will be
193
+ named something like `20151230163930_add_encryption_fields_to_users.rb`), and
194
+ add `unique: true` to the `add_index` line so that it looks like this:
195
+
196
+ ```ruby
197
+ add_index :users, :encrypted_otp_secret_key, unique: true
198
+ ```
199
+ Save the file.
200
+
201
+ 2. Run the migration: `bundle exec rake db:migrate`
202
+
203
+ 2. Update the gem: `bundle update two_factor_authentication`
204
+
205
+ 3. Add `encrypted: true` to `has_one_time_password` in your model.
206
+ For example: `has_one_time_password(encrypted: true)`
207
+
208
+ 4. Generate a migration to populate the new encryption fields:
209
+ ```
210
+ rails g migration PopulateEncryptedOtpFields
211
+ ```
212
+
213
+ Open the generated file, and replace its contents with the following:
214
+ ```ruby
215
+ class PopulateEncryptedOtpFields < ActiveRecord::Migration
216
+ def up
217
+ User.reset_column_information
218
+
219
+ User.find_each do |user|
220
+ user.otp_secret_key = user.read_attribute('otp_secret_key')
221
+ user.save!
222
+ end
223
+ end
224
+
225
+ def down
226
+ User.reset_column_information
227
+
228
+ User.find_each do |user|
229
+ user.otp_secret_key = ROTP::Base32.random_base32
230
+ user.save!
231
+ end
232
+ end
233
+ end
234
+ ```
235
+
236
+ 5. Generate a migration to remove the `:otp_secret_key` column:
237
+ ```
238
+ rails g migration RemoveOtpSecretKeyFromUsers otp_secret_key:string
239
+ ```
240
+
241
+ 6. Run the migrations: `bundle exec rake db:migrate`
242
+
243
+ If, for some reason, you want to switch back to the old non-encrypted version,
244
+ use these steps:
245
+
246
+ 1. Remove `(encrypted: true)` from `has_one_time_password`
247
+
248
+ 2. Roll back the last 3 migrations (assuming you haven't added any new ones
249
+ after them):
250
+ ```
251
+ bundle exec rake db:rollback STEP=3
252
+ ```
253
+
254
+ #### Critical Security Note! Add before_action to your user registration controllers
255
+
256
+ You should have a file registrations_controller.rb in your controllers folder
257
+ to overwrite/customize user registrations. It should include the lines below, for 2FA protection of user model updates, meaning that users can only access the users/edit page after confirming 2FA fully, not simply by logging in. Otherwise the entire 2FA system can be bypassed!
258
+
259
+ ```ruby
260
+ class RegistrationsController < Devise::RegistrationsController
261
+ before_action :two_factor_authenticate!, except: [:new, :create, :cancel]
262
+ end
263
+ ```
264
+
265
+
266
+ ### Example App
267
+ (This gem is not 100% compatible with this example app)
268
+ [TwoFactorAuthenticationExample](https://github.com/Houdini/TwoFactorAuthenticationExample)
269
+
270
+
271
+ ### Example user actions
272
+
273
+ to use an ENV VAR for the 2FA encryption key:
274
+
275
+ config.otp_secret_encryption_key = ENV['OTP_SECRET_ENCRYPTION_KEY']
276
+
277
+ to set up TOTP for Google Authenticator for user:
278
+
279
+ ```
280
+ current_user.otp_secret_key = current_user.generate_totp_secret
281
+ current_user.save!
282
+ ```
283
+
284
+ ( encrypted db fields are set upon user model save action,
285
+ rails c access relies on setting env var: OTP_SECRET_ENCRYPTION_KEY )
286
+
287
+ to check if user has input the correct code (from the QR display page)
288
+ before saving the user model:
289
+
290
+ ```
291
+ current_user.authenticate_totp('123456')
292
+ ```
293
+
294
+ additional note:
295
+
296
+ ```
297
+ current_user.otp_secret_key
298
+ ```
299
+
300
+ This returns the OTP secret key in plaintext for the user (if you have set the env var) in the console
301
+ the string used for generating the QR given to the user for their Google Auth is something like:
302
+
303
+ otpauth://totp/LABEL?secret=p6wwetjnkjnrcmpd (example secret used here)
304
+
305
+ where LABEL should be something like "example.com (Username)", which shows up in their GA app to remind them the code is for example.com
306
+
307
+ this returns true or false with an allowed_otp_drift_seconds 'grace period'
308
+
309
+ to set TOTP to DISABLED for a user account:
310
+
311
+ ```
312
+ current_user.second_factor_attempts_count=nil
313
+ current_user.encrypted_otp_secret_key=nil
314
+ current_user.direct_otp=nil
315
+ current_user.direct_otp_sent_at=nil
316
+ current_user.totp_timestamp=nil
317
+ current_user.direct_otp=nil
318
+ current_user.otp_secret_key=nil
319
+ current_user.save! (if in ruby code instead of console)
320
+ current_user.direct_otp? => false
321
+ current_user.totp_enabled? => false
322
+ ```
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ APP_RAKEFILE = File.expand_path("../spec/rails_app/Rakefile", __FILE__)
4
+ load 'rails/tasks/engine.rake'
5
+
6
+ require 'rspec/core/rake_task'
7
+
8
+ desc "Run all specs in spec directory (excluding plugin specs)"
9
+ task :default => :spec
10
+
11
+ # To test against a specific version of Rails
12
+ # export RAILS_VERSION=3.2.0; bundle update; rake
@@ -0,0 +1,79 @@
1
+ require 'devise/version'
2
+
3
+ class Devise::TotpController < DeviseController
4
+ prepend_before_action :authenticate_scope!
5
+ before_action :two_factor_authenticate!
6
+
7
+ def new
8
+ @otp_secret = resource.generate_totp_secret
9
+ @otp_secret_signature = sign_otp_secret(@otp_secret)
10
+ render_enroll_form
11
+ end
12
+
13
+ def create
14
+ @otp_secret_signature = params[:otp_secret_signature]
15
+ @otp_secret = verify_otp_secret(@otp_secret_signature)
16
+ if resource.enroll_totp!(@otp_secret, params[:otp_attempt])
17
+ after_two_factor_enroll_success_for(resource)
18
+ else
19
+ flash.now[:error] = 'The authenticator code provided was invalid!'
20
+ render_enroll_form
21
+ end
22
+ rescue ActiveSupport::MessageVerifier::InvalidSignature
23
+ redirect_to send("new_#{resource_name}_two_factor_authentication_path"), flash: { error: 'There has been a problem in the configuration process, please try again.' }
24
+ end
25
+
26
+ def show
27
+ end
28
+
29
+ def destroy
30
+ end
31
+
32
+ private
33
+
34
+ def generate_qr_code(otp_secret)
35
+ return unless defined?(::RQRCode)
36
+
37
+ qr_code = RQRCode::QRCode
38
+ .new(resource.provisioning_uri(nil, otp_secret_key: @otp_secret, issuer: Devise.otp_issuer))
39
+ .as_png(resize_exactly_to: 246)
40
+ .to_data_url
41
+ end
42
+
43
+ def render_enroll_form
44
+ @qr_code = generate_qr_code(@otp_secret)
45
+ render :new
46
+ end
47
+
48
+ def verifier
49
+ ActiveSupport::MessageVerifier.new(Devise.secret_key, digest: 'SHA256')
50
+ end
51
+
52
+ def verify_otp_secret(otp_secret_signature)
53
+ data = verifier.verify(otp_secret_signature)
54
+ valid = data[Devise.second_factor_resource_id] == resource[Devise.second_factor_resource_id]
55
+ raise ActiveSupport::MessageVerifier::InvalidSignature unless valid
56
+
57
+ data['otp_secret']
58
+ end
59
+
60
+ def sign_otp_secret(otp_secret)
61
+ data = {
62
+ Devise.second_factor_resource_id => resource[Devise.second_factor_resource_id],
63
+ 'otp_secret' => otp_secret,
64
+ }
65
+ verifier.generate(data)
66
+ end
67
+
68
+ def after_two_factor_enroll_success_for(resource)
69
+ redirect_to after_two_factor_enroll_success_path_for(resource), flash: { success: 'Multi-factor authentication successfully setup!' }
70
+ end
71
+
72
+ def after_two_factor_enroll_success_path_for(resource)
73
+ :root
74
+ end
75
+
76
+ def authenticate_scope!
77
+ self.resource = send("current_#{resource_name}")
78
+ end
79
+ end