devise-otp 0.4.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/Rakefile +17 -18
- data/app/controllers/devise_otp/devise/otp_credentials_controller.rb +15 -21
- data/app/controllers/devise_otp/devise/otp_tokens_controller.rb +7 -11
- data/app/views/devise/otp_credentials/show.html.erb +1 -1
- data/app/views/devise/otp_tokens/_token_secret.html.erb +4 -4
- data/app/views/devise/otp_tokens/recovery.html.erb +4 -4
- data/app/views/devise/otp_tokens/show.html.erb +5 -5
- data/config/locales/en.yml +4 -12
- data/devise-otp.gemspec +13 -13
- data/lib/devise-otp/version.rb +1 -1
- data/lib/devise-otp.rb +15 -29
- data/lib/devise_otp_authenticatable/controllers/helpers.rb +21 -23
- data/lib/devise_otp_authenticatable/controllers/url_helpers.rb +0 -2
- data/lib/devise_otp_authenticatable/engine.rb +6 -4
- data/lib/devise_otp_authenticatable/hooks/sessions.rb +6 -6
- data/lib/devise_otp_authenticatable/hooks.rb +1 -3
- data/lib/devise_otp_authenticatable/models/otp_authenticatable.rb +19 -25
- data/lib/devise_otp_authenticatable/routes.rb +11 -14
- data/lib/generators/active_record/devise_otp_generator.rb +1 -1
- data/lib/generators/devise_otp/devise_otp_generator.rb +12 -13
- data/lib/generators/devise_otp/install_generator.rb +3 -4
- data/lib/generators/devise_otp/views_generator.rb +5 -5
- data/test/dummy/Rakefile +1 -1
- data/test/dummy/app/controllers/posts_controller.rb +2 -2
- data/test/dummy/app/models/user.rb +8 -8
- data/test/dummy/config/application.rb +4 -4
- data/test/dummy/config/boot.rb +5 -5
- data/test/dummy/config/environment.rb +1 -1
- data/test/dummy/config/environments/development.rb +1 -1
- data/test/dummy/config/environments/production.rb +1 -1
- data/test/dummy/config/environments/test.rb +2 -2
- data/test/dummy/config/initializers/devise.rb +6 -8
- data/test/dummy/config/initializers/secret_token.rb +2 -2
- data/test/dummy/config/initializers/session_store.rb +1 -1
- data/test/dummy/config/initializers/wrap_parameters.rb +1 -1
- data/test/dummy/config/routes.rb +1 -1
- data/test/dummy/config.ru +1 -1
- data/test/dummy/db/migrate/20130131092406_add_devise_to_users.rb +12 -13
- data/test/dummy/db/migrate/20130131160351_devise_otp_add_to_users.rb +13 -13
- data/test/dummy/script/rails +3 -3
- data/test/integration/persistence_test.rb +11 -12
- data/test/integration/refresh_test.rb +13 -14
- data/test/integration/sign_in_test.rb +24 -26
- data/test/integration/token_test.rb +5 -6
- data/test/integration_tests_helper.rb +16 -17
- data/test/model_tests_helper.rb +5 -7
- data/test/models/otp_authenticatable_test.rb +18 -19
- data/test/test_helper.rb +10 -10
- metadata +24 -64
@@ -4,7 +4,7 @@ module DeviseOtpAuthenticatable::Hooks
|
|
4
4
|
include DeviseOtpAuthenticatable::Controllers::UrlHelpers
|
5
5
|
|
6
6
|
included do
|
7
|
-
alias_method
|
7
|
+
alias_method :create, :create_with_otp
|
8
8
|
end
|
9
9
|
|
10
10
|
#
|
@@ -18,19 +18,19 @@ module DeviseOtpAuthenticatable::Hooks
|
|
18
18
|
|
19
19
|
otp_refresh_credentials_for(resource)
|
20
20
|
|
21
|
+
yield resource if block_given?
|
21
22
|
if otp_challenge_required_on?(resource)
|
22
23
|
challenge = resource.generate_otp_challenge!
|
23
24
|
warden.logout
|
24
25
|
store_location_for(resource, devise_stored_location) # restore the stored location
|
25
|
-
respond_with resource, :
|
26
|
+
respond_with resource, location: otp_credential_path_for(resource, {challenge: challenge})
|
26
27
|
elsif otp_mandatory_on?(resource) # if mandatory, log in user but send him to the must activate otp
|
27
28
|
set_flash_message(:notice, :signed_in_but_otp) if is_navigational_format?
|
28
29
|
sign_in(resource_name, resource)
|
29
|
-
respond_with resource, :
|
30
|
+
respond_with resource, location: otp_token_path_for(resource)
|
30
31
|
else
|
31
|
-
set_flash_message(:notice, :signed_in) if is_navigational_format?
|
32
32
|
sign_in(resource_name, resource)
|
33
|
-
respond_with resource, :
|
33
|
+
respond_with resource, location: after_sign_in_path_for(resource)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -49,7 +49,7 @@ module DeviseOtpAuthenticatable::Hooks
|
|
49
49
|
# the resource -should- have otp turned on, but it isn't
|
50
50
|
#
|
51
51
|
def otp_mandatory_on?(resource)
|
52
|
-
return true if resource.class.otp_mandatory
|
52
|
+
return true if resource.class.otp_mandatory && !resource.otp_enabled
|
53
53
|
return false unless resource.respond_to?(:otp_mandatory)
|
54
54
|
|
55
55
|
resource.otp_mandatory && !resource.otp_enabled
|
@@ -1,13 +1,11 @@
|
|
1
1
|
module DeviseOtpAuthenticatable
|
2
2
|
module Hooks
|
3
|
-
|
4
|
-
autoload :Sessions, 'devise_otp_authenticatable/hooks/sessions.rb'
|
3
|
+
autoload :Sessions, "devise_otp_authenticatable/hooks/sessions.rb"
|
5
4
|
|
6
5
|
class << self
|
7
6
|
def apply
|
8
7
|
::Devise::SessionsController.send(:include, Hooks::Sessions)
|
9
8
|
end
|
10
9
|
end
|
11
|
-
|
12
10
|
end
|
13
11
|
end
|
@@ -1,27 +1,27 @@
|
|
1
|
-
require
|
1
|
+
require "rotp"
|
2
2
|
|
3
3
|
module Devise::Models
|
4
4
|
module OtpAuthenticatable
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
before_validation :generate_otp_auth_secret, :
|
9
|
-
before_validation :generate_otp_persistence_seed, :
|
10
|
-
scope :with_valid_otp_challenge, lambda { |time| where(
|
8
|
+
before_validation :generate_otp_auth_secret, on: :create
|
9
|
+
before_validation :generate_otp_persistence_seed, on: :create
|
10
|
+
scope :with_valid_otp_challenge, lambda { |time| where("otp_challenge_expires > ?", time) }
|
11
11
|
end
|
12
12
|
|
13
13
|
module ClassMethods
|
14
14
|
::Devise::Models.config(self, :otp_authentication_timeout, :otp_drift_window, :otp_trust_persistence,
|
15
|
-
|
16
|
-
|
15
|
+
:otp_mandatory, :otp_credentials_refresh, :otp_issuer, :otp_recovery_tokens,
|
16
|
+
:otp_controller_path)
|
17
17
|
|
18
18
|
def find_valid_otp_challenge(challenge)
|
19
|
-
with_valid_otp_challenge(Time.now).where(:
|
19
|
+
with_valid_otp_challenge(Time.now).where(otp_session_challenge: challenge).first
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
def time_based_otp
|
24
|
-
@time_based_otp ||= ROTP::TOTP.new(otp_auth_secret, issuer:
|
24
|
+
@time_based_otp ||= ROTP::TOTP.new(otp_auth_secret, issuer: (self.class.otp_issuer || Rails.application.class.module_parent_name).to_s)
|
25
25
|
end
|
26
26
|
|
27
27
|
def recovery_otp
|
@@ -36,15 +36,14 @@ module Devise::Models
|
|
36
36
|
email
|
37
37
|
end
|
38
38
|
|
39
|
-
|
40
39
|
def reset_otp_credentials
|
41
40
|
@time_based_otp = nil
|
42
41
|
@recovery_otp = nil
|
43
42
|
generate_otp_auth_secret
|
44
43
|
reset_otp_persistence
|
45
|
-
update!(:
|
46
|
-
|
47
|
-
|
44
|
+
update!(otp_enabled: false,
|
45
|
+
otp_session_challenge: nil, otp_challenge_expires: nil,
|
46
|
+
otp_recovery_counter: 0)
|
48
47
|
end
|
49
48
|
|
50
49
|
def reset_otp_credentials!
|
@@ -66,16 +65,16 @@ module Devise::Models
|
|
66
65
|
reset_otp_credentials!
|
67
66
|
end
|
68
67
|
|
69
|
-
update!(:
|
68
|
+
update!(otp_enabled: true, otp_enabled_on: Time.now)
|
70
69
|
end
|
71
70
|
|
72
71
|
def disable_otp!
|
73
|
-
update!(:
|
72
|
+
update!(otp_enabled: false, otp_enabled_on: nil)
|
74
73
|
end
|
75
74
|
|
76
75
|
def generate_otp_challenge!(expires = nil)
|
77
|
-
update!(:
|
78
|
-
|
76
|
+
update!(otp_session_challenge: SecureRandom.hex,
|
77
|
+
otp_challenge_expires: DateTime.now + (expires || self.class.otp_authentication_timeout))
|
79
78
|
otp_session_challenge
|
80
79
|
end
|
81
80
|
|
@@ -83,7 +82,6 @@ module Devise::Models
|
|
83
82
|
(otp_challenge_expires.nil? || otp_challenge_expires > Time.now)
|
84
83
|
end
|
85
84
|
|
86
|
-
|
87
85
|
def validate_otp_token(token, recovery = false)
|
88
86
|
if recovery
|
89
87
|
validate_otp_recovery_token token
|
@@ -100,9 +98,8 @@ module Devise::Models
|
|
100
98
|
alias_method :valid_otp_time_token?, :validate_otp_time_token
|
101
99
|
|
102
100
|
def next_otp_recovery_tokens(number = self.class.otp_recovery_tokens)
|
103
|
-
(otp_recovery_counter..otp_recovery_counter + number).
|
101
|
+
(otp_recovery_counter..otp_recovery_counter + number).each_with_object({}) do |index, h|
|
104
102
|
h[index] = recovery_otp.at(index)
|
105
|
-
h
|
106
103
|
end
|
107
104
|
end
|
108
105
|
|
@@ -114,15 +111,13 @@ module Devise::Models
|
|
114
111
|
end
|
115
112
|
alias_method :valid_otp_recovery_token?, :validate_otp_recovery_token
|
116
113
|
|
117
|
-
|
118
|
-
|
119
114
|
private
|
120
115
|
|
121
116
|
def validate_otp_token_with_drift(token)
|
122
|
-
|
123
117
|
# should be centered around saved drift
|
124
|
-
(-self.class.otp_drift_window..self.class.otp_drift_window).any? {|drift|
|
125
|
-
|
118
|
+
(-self.class.otp_drift_window..self.class.otp_drift_window).any? { |drift|
|
119
|
+
time_based_otp.verify(token, at: Time.now.ago(30 * drift))
|
120
|
+
}
|
126
121
|
end
|
127
122
|
|
128
123
|
def generate_otp_persistence_seed
|
@@ -133,6 +128,5 @@ module Devise::Models
|
|
133
128
|
self.otp_auth_secret = ROTP::Base32.random_base32
|
134
129
|
self.otp_recovery_secret = ROTP::Base32.random_base32
|
135
130
|
end
|
136
|
-
|
137
131
|
end
|
138
132
|
end
|
@@ -1,27 +1,24 @@
|
|
1
1
|
module ActionDispatch::Routing
|
2
2
|
class Mapper
|
3
|
-
|
4
3
|
protected
|
5
4
|
|
6
5
|
def devise_otp(mapping, controllers)
|
7
|
-
namespace :otp, :
|
8
|
-
resource :token, :
|
9
|
-
|
10
|
-
|
6
|
+
namespace :otp, module: :devise_otp do
|
7
|
+
resource :token, only: [:show, :update, :destroy],
|
8
|
+
path: mapping.path_names[:token], controller: controllers[:otp_tokens] do
|
11
9
|
if Devise.otp_trust_persistence
|
12
|
-
get
|
13
|
-
post :persistence, :
|
14
|
-
delete :persistence, :
|
10
|
+
get :persistence, action: "get_persistence"
|
11
|
+
post :persistence, action: "clear_persistence"
|
12
|
+
delete :persistence, action: "delete_persistence"
|
15
13
|
end
|
16
14
|
|
17
|
-
get
|
15
|
+
get :recovery
|
18
16
|
end
|
19
17
|
|
20
|
-
resource :credential, :
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
put :refresh, :action => 'set_refresh'
|
18
|
+
resource :credential, only: [:show, :update],
|
19
|
+
path: mapping.path_names[:credentials], controller: controllers[:otp_credentials] do
|
20
|
+
get :refresh, action: "get_refresh"
|
21
|
+
put :refresh, action: "set_refresh"
|
25
22
|
end
|
26
23
|
end
|
27
24
|
end
|
@@ -1,17 +1,16 @@
|
|
1
1
|
module DeviseOtp
|
2
|
-
|
3
|
-
|
2
|
+
module Generators
|
3
|
+
class DeviseOtpGenerator < Rails::Generators::NamedBase
|
4
|
+
namespace "devise_otp"
|
4
5
|
|
5
|
-
|
6
|
+
desc "Add :otp_authenticatable directive in the given model, plus accessors. Also generate migration for ActiveRecord"
|
6
7
|
|
7
|
-
|
8
|
+
def inject_devise_otp_content
|
9
|
+
path = File.join("app", "models", "#{file_path}.rb")
|
10
|
+
inject_into_file(path, "otp_authenticatable, :", after: "devise :") if File.exist?(path)
|
11
|
+
end
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
hook_for :orm
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
13
|
+
hook_for :orm
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -7,8 +7,7 @@ module DeviseOtp
|
|
7
7
|
desc "Install the devise OTP authentication extension"
|
8
8
|
|
9
9
|
def add_configs
|
10
|
-
|
11
|
-
content = <<-CONTENT
|
10
|
+
content = <<-CONTENT
|
12
11
|
|
13
12
|
# ==> Devise OTP Extension
|
14
13
|
# Configure OTP extension for devise
|
@@ -43,9 +42,9 @@ content = <<-CONTENT
|
|
43
42
|
# Custom view path for Devise OTP controllers
|
44
43
|
#config.otp_controller_path = 'devise'
|
45
44
|
|
46
|
-
CONTENT
|
45
|
+
CONTENT
|
47
46
|
|
48
|
-
inject_into_file "config/initializers/devise.rb", content, :
|
47
|
+
inject_into_file "config/initializers/devise.rb", content, before: /end[ |\n]+\Z/
|
49
48
|
end
|
50
49
|
|
51
50
|
def copy_locale
|
@@ -1,17 +1,17 @@
|
|
1
|
-
require
|
1
|
+
require "generators/devise/views_generator"
|
2
2
|
|
3
3
|
module DeviseOtp
|
4
4
|
module Generators
|
5
5
|
class ViewsGenerator < Rails::Generators::Base
|
6
|
-
desc
|
6
|
+
desc "Copies all Devise OTP views to your application."
|
7
7
|
|
8
|
-
argument :scope, :
|
9
|
-
|
8
|
+
argument :scope, required: false, default: nil,
|
9
|
+
desc: "The scope to copy views to"
|
10
10
|
|
11
11
|
include ::Devise::Generators::ViewPathTemplates
|
12
12
|
source_root File.expand_path("../../../../app/views", __FILE__)
|
13
13
|
def copy_views
|
14
|
-
view_directory :devise,
|
14
|
+
view_directory :devise, "app/views/devise"
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/test/dummy/Rakefile
CHANGED
@@ -2,6 +2,6 @@
|
|
2
2
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
3
3
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
4
4
|
|
5
|
-
require File.expand_path(
|
5
|
+
require File.expand_path("../config/application", __FILE__)
|
6
6
|
|
7
7
|
Dummy::Application.load_tasks
|
@@ -46,7 +46,7 @@ class PostsController < ApplicationController
|
|
46
46
|
|
47
47
|
respond_to do |format|
|
48
48
|
if @post.save
|
49
|
-
format.html { redirect_to @post, notice:
|
49
|
+
format.html { redirect_to @post, notice: "Post was successfully created." }
|
50
50
|
format.json { render json: @post, status: :created, location: @post }
|
51
51
|
else
|
52
52
|
format.html { render action: "new" }
|
@@ -62,7 +62,7 @@ class PostsController < ApplicationController
|
|
62
62
|
|
63
63
|
respond_to do |format|
|
64
64
|
if @post.update_attributes(params[:post])
|
65
|
-
format.html { redirect_to @post, notice:
|
65
|
+
format.html { redirect_to @post, notice: "Post was successfully updated." }
|
66
66
|
format.json { head :ok }
|
67
67
|
else
|
68
68
|
format.html { render action: "edit" }
|
@@ -3,18 +3,18 @@ class User < PARENT_MODEL_CLASS
|
|
3
3
|
include Mongoid::Document
|
4
4
|
|
5
5
|
## Database authenticatable
|
6
|
-
field :email,
|
7
|
-
field :encrypted_password, :
|
6
|
+
field :email, type: String, null: false, default: ""
|
7
|
+
field :encrypted_password, type: String, null: false, default: ""
|
8
8
|
|
9
9
|
## Recoverable
|
10
|
-
field :reset_password_token,
|
11
|
-
field :reset_password_sent_at, :
|
10
|
+
field :reset_password_token, type: String
|
11
|
+
field :reset_password_sent_at, type: Time
|
12
12
|
end
|
13
13
|
|
14
14
|
devise :otp_authenticatable, :database_authenticatable, :registerable,
|
15
|
-
|
15
|
+
:trackable, :validatable
|
16
16
|
|
17
17
|
# Setup accessible (or protected) attributes for your model
|
18
|
-
#attr_accessible :otp_enabled, :otp_mandatory, :as => :otp_privileged
|
19
|
-
#attr_accessible :email, :password, :password_confirmation, :remember_me
|
20
|
-
end
|
18
|
+
# attr_accessible :otp_enabled, :otp_mandatory, :as => :otp_privileged
|
19
|
+
# attr_accessible :email, :password, :password_confirmation, :remember_me
|
20
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require File.expand_path(
|
1
|
+
require File.expand_path("../boot", __FILE__)
|
2
2
|
|
3
3
|
# Pick the frameworks you want:
|
4
4
|
require "active_record/railtie"
|
5
5
|
require "action_controller/railtie"
|
6
6
|
require "action_mailer/railtie"
|
7
|
-
#require "active_resource/railtie"
|
7
|
+
# require "active_resource/railtie"
|
8
8
|
require "sprockets/railtie"
|
9
9
|
# require "rails/test_unit/railtie"
|
10
10
|
|
@@ -15,7 +15,7 @@ begin
|
|
15
15
|
require "#{DEVISE_ORM}/railtie"
|
16
16
|
rescue LoadError
|
17
17
|
end
|
18
|
-
PARENT_MODEL_CLASS = DEVISE_ORM == :active_record ? ActiveRecord::Base : Object
|
18
|
+
PARENT_MODEL_CLASS = (DEVISE_ORM == :active_record) ? ActiveRecord::Base : Object
|
19
19
|
|
20
20
|
require "devise"
|
21
21
|
require "devise-otp"
|
@@ -64,6 +64,6 @@ module Dummy
|
|
64
64
|
config.assets.enabled = true
|
65
65
|
|
66
66
|
# Version of your assets, change this if you want to expire all your assets
|
67
|
-
config.assets.version =
|
67
|
+
config.assets.version = "1.0"
|
68
68
|
end
|
69
69
|
end
|
data/test/dummy/config/boot.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
gemfile = File.expand_path(
|
1
|
+
require "rubygems"
|
2
|
+
gemfile = File.expand_path("../../../../Gemfile", __FILE__)
|
3
3
|
|
4
4
|
if File.exist?(gemfile)
|
5
|
-
ENV[
|
6
|
-
require
|
5
|
+
ENV["BUNDLE_GEMFILE"] = gemfile
|
6
|
+
require "bundler"
|
7
7
|
Bundler.setup
|
8
8
|
end
|
9
9
|
|
10
|
-
$:.unshift File.expand_path(
|
10
|
+
$:.unshift File.expand_path("../../../../lib", __FILE__)
|
@@ -10,7 +10,7 @@ Dummy::Application.configure do
|
|
10
10
|
config.eager_load = false
|
11
11
|
|
12
12
|
# Show full error reports and disable caching
|
13
|
-
config.consider_all_requests_local
|
13
|
+
config.consider_all_requests_local = true
|
14
14
|
config.action_controller.perform_caching = false
|
15
15
|
|
16
16
|
# Don't care if the mailer can't send
|
@@ -11,7 +11,7 @@ Dummy::Application.configure do
|
|
11
11
|
config.eager_load = true
|
12
12
|
|
13
13
|
# Full error reports are disabled and caching is turned on
|
14
|
-
config.consider_all_requests_local
|
14
|
+
config.consider_all_requests_local = false
|
15
15
|
config.action_controller.perform_caching = true
|
16
16
|
|
17
17
|
# Disable Rails's static asset server (Apache or nginx will already do this)
|
@@ -17,14 +17,14 @@ Dummy::Application.configure do
|
|
17
17
|
config.static_cache_control = "public, max-age=3600"
|
18
18
|
|
19
19
|
# Show full error reports and disable caching
|
20
|
-
config.consider_all_requests_local
|
20
|
+
config.consider_all_requests_local = true
|
21
21
|
config.action_controller.perform_caching = false
|
22
22
|
|
23
23
|
# Raise exceptions instead of rendering exception templates
|
24
24
|
config.action_dispatch.show_exceptions = false
|
25
25
|
|
26
26
|
# Disable request forgery protection in test environment
|
27
|
-
config.action_controller.allow_forgery_protection
|
27
|
+
config.action_controller.allow_forgery_protection = false
|
28
28
|
|
29
29
|
# Tell Action Mailer not to deliver emails to the real world.
|
30
30
|
# The :test delivery method accumulates sent emails in the
|
@@ -1,8 +1,7 @@
|
|
1
1
|
# Use this hook to configure devise mailer, warden hooks and so forth.
|
2
2
|
# Many of these configuration options can be set straight in your model.
|
3
3
|
Devise.setup do |config|
|
4
|
-
|
5
|
-
config.secret_key = '638da6a325f1de9038321504c4a06ef7f4f7f835331a63ba41b93732b3830d032b6a10b38afa67427e050b19f9717b1e7a45f650ac5631c53cc9dd85264fdfb0'
|
4
|
+
config.secret_key = "638da6a325f1de9038321504c4a06ef7f4f7f835331a63ba41b93732b3830d032b6a10b38afa67427e050b19f9717b1e7a45f650ac5631c53cc9dd85264fdfb0"
|
6
5
|
|
7
6
|
# ==> Mailer Configuration
|
8
7
|
# Configure the e-mail address which will be shown in Devise::Mailer,
|
@@ -16,7 +15,7 @@ Devise.setup do |config|
|
|
16
15
|
# Load and configure the ORM. Supports :active_record (default) and
|
17
16
|
# :mongoid (bson_ext recommended) by default. Other ORMs may be
|
18
17
|
# available as additional gems.
|
19
|
-
require
|
18
|
+
require "devise/orm/active_record"
|
20
19
|
|
21
20
|
# ==> Configuration for any authentication mechanism
|
22
21
|
# Configure which keys are used when authenticating a user. The default is
|
@@ -38,12 +37,12 @@ Devise.setup do |config|
|
|
38
37
|
# Configure which authentication keys should be case-insensitive.
|
39
38
|
# These keys will be downcased upon creating or modifying a user and when used
|
40
39
|
# to authenticate or find a user. Default is :email.
|
41
|
-
config.case_insensitive_keys = [
|
40
|
+
config.case_insensitive_keys = [:email]
|
42
41
|
|
43
42
|
# Configure which authentication keys should have whitespace stripped.
|
44
43
|
# These keys will have whitespace before and after removed upon creating or
|
45
44
|
# modifying a user and when used to authenticate or find a user. Default is :email.
|
46
|
-
config.strip_whitespace_keys = [
|
45
|
+
config.strip_whitespace_keys = [:email]
|
47
46
|
|
48
47
|
# Tell if authentication through request.params is enabled. True by default.
|
49
48
|
# It can be set to an array that will enable params authentication only for the
|
@@ -245,9 +244,8 @@ Devise.setup do |config|
|
|
245
244
|
# Configure extension for devise
|
246
245
|
|
247
246
|
# How long should the user have to enter their token. To change the default, uncomment and change the below:
|
248
|
-
#config.otp_authentication_timeout = 3.minutes
|
247
|
+
# config.otp_authentication_timeout = 3.minutes
|
249
248
|
|
250
249
|
# Change time drift settings for valid token values. To change the default, uncomment and change the below:
|
251
|
-
#config.otp_authentication_time_drift = 3
|
252
|
-
|
250
|
+
# config.otp_authentication_time_drift = 3
|
253
251
|
end
|
@@ -4,5 +4,5 @@
|
|
4
4
|
# If you change this key, all old signed cookies will become invalid!
|
5
5
|
# Make sure the secret is at least 30 characters and all random,
|
6
6
|
# no regular words or you'll be exposed to dictionary attacks.
|
7
|
-
Dummy::Application.config.secret_token =
|
8
|
-
Dummy::Application.config.secret_key_base =
|
7
|
+
Dummy::Application.config.secret_token = "7854ba4c663086c191afbc2e05384503b5529fa2c8e51417539db1cbe7c68e8490e9d57a1d908d4e82816a522edb97f71a8de9233272a5598534a38ef1b08697"
|
8
|
+
Dummy::Application.config.secret_key_base = "7854ba4c663086c191afbc2e05384503b5529fa2c8e51417539db1cbe7c68e8490e9d57a1d908d4e82816a522edb97f71a8de9233272a5598534a38ef1b08697"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Be sure to restart your server when you modify this file.
|
2
2
|
|
3
|
-
Dummy::Application.config.session_store :cookie_store, :
|
3
|
+
Dummy::Application.config.session_store :cookie_store, key: "_dummy_session"
|
4
4
|
|
5
5
|
# Use the database for sessions instead of the cookie-based default,
|
6
6
|
# which shouldn't be used to store highly confidential information
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
7
7
|
ActiveSupport.on_load(:action_controller) do
|
8
|
-
wrap_parameters :
|
8
|
+
wrap_parameters format: [:json]
|
9
9
|
end
|
10
10
|
|
11
11
|
# Disable root element in JSON by default.
|
data/test/dummy/config/routes.rb
CHANGED
data/test/dummy/config.ru
CHANGED
@@ -2,22 +2,22 @@ class AddDeviseToUsers < ActiveRecord::Migration[5.0]
|
|
2
2
|
def self.up
|
3
3
|
change_table(:users) do |t|
|
4
4
|
## Database authenticatable
|
5
|
-
t.string :email,
|
6
|
-
t.string :encrypted_password, :
|
5
|
+
t.string :email, null: false, default: ""
|
6
|
+
t.string :encrypted_password, null: false, default: ""
|
7
7
|
|
8
8
|
## Recoverable
|
9
|
-
t.string
|
9
|
+
t.string :reset_password_token
|
10
10
|
t.datetime :reset_password_sent_at
|
11
11
|
|
12
12
|
## Rememberable
|
13
13
|
t.datetime :remember_created_at
|
14
14
|
|
15
15
|
## Trackable
|
16
|
-
t.integer
|
16
|
+
t.integer :sign_in_count, default: 0
|
17
17
|
t.datetime :current_sign_in_at
|
18
18
|
t.datetime :last_sign_in_at
|
19
|
-
t.string
|
20
|
-
t.string
|
19
|
+
t.string :current_sign_in_ip
|
20
|
+
t.string :last_sign_in_ip
|
21
21
|
|
22
22
|
## Confirmable
|
23
23
|
# t.string :confirmation_token
|
@@ -26,23 +26,22 @@ class AddDeviseToUsers < ActiveRecord::Migration[5.0]
|
|
26
26
|
# t.string :unconfirmed_email # Only if using reconfirmable
|
27
27
|
|
28
28
|
## Lockable
|
29
|
-
t.integer
|
30
|
-
t.string
|
29
|
+
t.integer :failed_attempts, default: 0 # Only if lock strategy is :failed_attempts
|
30
|
+
t.string :unlock_token # Only if unlock strategy is :email or :both
|
31
31
|
t.datetime :locked_at
|
32
32
|
|
33
33
|
## Token authenticatable
|
34
34
|
t.string :authentication_token
|
35
35
|
|
36
|
-
|
37
36
|
# Uncomment below if timestamps were not included in your original model.
|
38
37
|
# t.timestamps
|
39
38
|
end
|
40
39
|
|
41
|
-
add_index :users, :email,
|
42
|
-
add_index :users, :reset_password_token, :
|
40
|
+
add_index :users, :email, unique: true
|
41
|
+
add_index :users, :reset_password_token, unique: true
|
43
42
|
# add_index :users, :confirmation_token, :unique => true
|
44
|
-
add_index :users, :unlock_token,
|
45
|
-
add_index :users, :authentication_token, :
|
43
|
+
add_index :users, :unlock_token, unique: true
|
44
|
+
add_index :users, :authentication_token, unique: true
|
46
45
|
end
|
47
46
|
|
48
47
|
def self.down
|
@@ -1,28 +1,28 @@
|
|
1
1
|
class DeviseOtpAddToUsers < ActiveRecord::Migration[5.0]
|
2
2
|
def self.up
|
3
3
|
change_table :users do |t|
|
4
|
-
t.string
|
5
|
-
t.string
|
6
|
-
t.boolean
|
7
|
-
t.boolean
|
8
|
-
t.datetime
|
9
|
-
t.integer
|
10
|
-
t.integer
|
11
|
-
t.integer
|
12
|
-
t.string
|
4
|
+
t.string :otp_auth_secret
|
5
|
+
t.string :otp_recovery_secret
|
6
|
+
t.boolean :otp_enabled, default: false, null: false
|
7
|
+
t.boolean :otp_mandatory, default: false, null: false
|
8
|
+
t.datetime :otp_enabled_on
|
9
|
+
t.integer :otp_time_drift, default: 0, null: false
|
10
|
+
t.integer :otp_failed_attempts, default: 0, null: false
|
11
|
+
t.integer :otp_recovery_counter, default: 0, null: false
|
12
|
+
t.string :otp_persistence_seed
|
13
13
|
|
14
|
-
t.string
|
15
|
-
t.datetime
|
14
|
+
t.string :otp_session_challenge
|
15
|
+
t.datetime :otp_challenge_expires
|
16
16
|
end
|
17
17
|
|
18
|
-
add_index :users, :otp_session_challenge,
|
18
|
+
add_index :users, :otp_session_challenge, unique: true
|
19
19
|
add_index :users, :otp_challenge_expires
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.down
|
23
23
|
change_table :users do |t|
|
24
24
|
t.remove :otp_auth_secret, :otp_recovery_secret, :otp_enabled, :otp_mandatory, :otp_enabled_on, :otp_session_challenge,
|
25
|
-
|
25
|
+
:otp_challenge_expires, :otp_time_drift, :otp_failed_attempts, :otp_recovery_counter, :otp_persistence_seed
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|