devise-otp 0.2.3 → 0.3.0
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.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yml +36 -0
- data/.gitignore +0 -0
- data/Gemfile +1 -22
- data/LICENSE.txt +0 -0
- data/README.md +41 -74
- data/Rakefile +0 -0
- data/app/assets/javascripts/devise-otp.js +1 -0
- data/app/assets/javascripts/qrcode.js +609 -0
- data/app/controllers/devise_otp/devise/credentials_controller.rb +102 -0
- data/app/controllers/devise_otp/devise/tokens_controller.rb +112 -0
- data/app/views/devise/credentials/refresh.html.erb +19 -0
- data/app/views/devise/credentials/show.html.erb +31 -0
- data/app/views/devise/tokens/_token_secret.html.erb +23 -0
- data/app/views/devise/tokens/_trusted_devices.html.erb +12 -0
- data/app/views/devise/tokens/recovery.html.erb +21 -0
- data/app/views/devise/tokens/recovery_codes.text.erb +3 -0
- data/app/views/devise/tokens/show.html.erb +21 -0
- data/config/locales/en.yml +8 -8
- data/devise-otp.gemspec +14 -9
- data/docs/QR_CODES.md +48 -0
- data/lib/devise-otp/version.rb +1 -1
- data/lib/devise-otp.rb +12 -11
- data/lib/devise_otp_authenticatable/controllers/helpers.rb +20 -12
- data/lib/devise_otp_authenticatable/controllers/url_helpers.rb +6 -7
- data/lib/devise_otp_authenticatable/engine.rb +22 -13
- data/lib/devise_otp_authenticatable/hooks/sessions.rb +8 -7
- data/lib/devise_otp_authenticatable/hooks.rb +1 -1
- data/lib/devise_otp_authenticatable/models/otp_authenticatable.rb +14 -9
- data/lib/devise_otp_authenticatable/routes.rb +4 -7
- data/lib/generators/active_record/devise_otp_generator.rb +0 -0
- data/lib/generators/active_record/templates/migration.rb +1 -1
- data/lib/generators/devise_otp/devise_otp_generator.rb +0 -0
- data/lib/generators/devise_otp/install_generator.rb +8 -5
- data/lib/generators/devise_otp/views_generator.rb +2 -3
- data/test/dummy/README.rdoc +0 -0
- data/test/dummy/Rakefile +0 -0
- data/test/dummy/app/assets/config/manifest.js +2 -0
- data/test/dummy/app/assets/javascripts/application.js +1 -0
- data/test/dummy/app/assets/stylesheets/application.css +0 -0
- data/test/dummy/app/controllers/application_controller.rb +1 -1
- data/test/dummy/app/controllers/posts_controller.rb +2 -0
- data/test/dummy/app/helpers/application_helper.rb +0 -0
- data/test/dummy/app/helpers/posts_helper.rb +0 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/post.rb +0 -0
- data/test/dummy/app/models/user.rb +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +0 -0
- data/test/dummy/app/views/posts/_form.html.erb +0 -0
- data/test/dummy/app/views/posts/edit.html.erb +0 -0
- data/test/dummy/app/views/posts/index.html.erb +0 -0
- data/test/dummy/app/views/posts/new.html.erb +0 -0
- data/test/dummy/app/views/posts/show.html.erb +0 -0
- data/test/dummy/config/application.rb +2 -1
- data/test/dummy/config/boot.rb +0 -0
- data/test/dummy/config/database.yml +1 -1
- data/test/dummy/config/environment.rb +0 -0
- data/test/dummy/config/environments/development.rb +0 -7
- data/test/dummy/config/environments/production.rb +0 -4
- data/test/dummy/config/environments/test.rb +0 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +0 -0
- data/test/dummy/config/initializers/devise.rb +0 -0
- data/test/dummy/config/initializers/inflections.rb +0 -0
- data/test/dummy/config/initializers/mime_types.rb +0 -0
- data/test/dummy/config/initializers/secret_token.rb +0 -0
- data/test/dummy/config/initializers/session_store.rb +0 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +0 -0
- data/test/dummy/config/locales/en.yml +0 -0
- data/test/dummy/config/routes.rb +0 -0
- data/test/dummy/config.ru +0 -0
- data/test/dummy/db/migrate/20130125101430_create_users.rb +1 -1
- data/test/dummy/db/migrate/20130131092406_add_devise_to_users.rb +1 -1
- data/test/dummy/db/migrate/20130131142320_create_posts.rb +1 -1
- data/test/dummy/db/migrate/20130131160351_devise_otp_add_to_users.rb +2 -2
- data/test/dummy/db/test.sqlite3-journal +0 -0
- data/test/dummy/lib/assets/.gitkeep +0 -0
- data/test/dummy/public/404.html +0 -0
- data/test/dummy/public/422.html +0 -0
- data/test/dummy/public/500.html +0 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/integration/persistence_test.rb +18 -2
- data/test/integration/refresh_test.rb +2 -32
- data/test/integration/sign_in_test.rb +3 -3
- data/test/integration/token_test.rb +1 -4
- data/test/integration_tests_helper.rb +0 -1
- data/test/model_tests_helper.rb +0 -0
- data/test/models/otp_authenticatable_test.rb +8 -9
- data/test/orm/active_record.rb +3 -1
- data/test/test_helper.rb +71 -2
- metadata +146 -40
- data/.travis.yml +0 -12
- data/app/controllers/devise_otp/credentials_controller.rb +0 -106
- data/app/controllers/devise_otp/tokens_controller.rb +0 -105
- data/app/views/devise_otp/credentials/refresh.html.erb +0 -20
- data/app/views/devise_otp/credentials/show.html.erb +0 -23
- data/app/views/devise_otp/tokens/_token_secret.html.erb +0 -17
- data/app/views/devise_otp/tokens/_trusted_devices.html.erb +0 -10
- data/app/views/devise_otp/tokens/recovery.html.erb +0 -21
- data/app/views/devise_otp/tokens/show.html.erb +0 -19
- data/lib/devise_otp_authenticatable/mapping.rb +0 -19
|
@@ -3,17 +3,17 @@ require 'model_tests_helper'
|
|
|
3
3
|
|
|
4
4
|
class OtpAuthenticatableTest < ActiveSupport::TestCase
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
def setup
|
|
7
|
+
new_user
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
test 'new users have a non-nil secret set' do
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
assert_not_nil User.first.otp_auth_secret
|
|
12
|
+
end
|
|
13
13
|
|
|
14
14
|
test 'new users have OTP disabled by default' do
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
assert !User.first.otp_enabled
|
|
16
|
+
end
|
|
17
17
|
|
|
18
18
|
test 'users should have an instance of TOTP/ROTP objects' do
|
|
19
19
|
u = User.first
|
|
@@ -115,8 +115,7 @@ class OtpAuthenticatableTest < ActiveSupport::TestCase
|
|
|
115
115
|
recovery = u.next_otp_recovery_tokens
|
|
116
116
|
|
|
117
117
|
assert u.valid_otp_recovery_token? recovery.fetch(0)
|
|
118
|
-
|
|
118
|
+
assert_nil u.valid_otp_recovery_token?(recovery.fetch(0))
|
|
119
119
|
assert u.valid_otp_recovery_token? recovery.fetch(2)
|
|
120
120
|
end
|
|
121
|
-
|
|
122
|
-
end
|
|
121
|
+
end
|
data/test/orm/active_record.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
ActiveRecord::Migration.verbose = false
|
|
2
2
|
ActiveRecord::Base.logger = Logger.new(nil)
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
migrations_path = File.expand_path("../../dummy/db/migrate/", __FILE__)
|
|
5
|
+
|
|
6
|
+
ActiveRecord::MigrationContext.new(migrations_path, ActiveRecord::SchemaMigration).migrate
|
data/test/test_helper.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
ENV["RAILS_ENV"] = "test"
|
|
2
2
|
DEVISE_ORM = (ENV["DEVISE_ORM"] || :active_record).to_sym
|
|
3
3
|
|
|
4
|
-
$:.unshift File.dirname(__FILE__)
|
|
5
4
|
puts "\n==> Devise.orm = #{DEVISE_ORM.inspect}"
|
|
6
5
|
require "dummy/config/environment"
|
|
7
6
|
require "orm/#{DEVISE_ORM}"
|
|
8
7
|
require 'rails/test_help'
|
|
9
8
|
require 'capybara/rails'
|
|
9
|
+
require 'capybara/cuprite'
|
|
10
10
|
require 'minitest/reporters'
|
|
11
11
|
|
|
12
12
|
MiniTest::Reporters.use!
|
|
@@ -15,8 +15,77 @@ MiniTest::Reporters.use!
|
|
|
15
15
|
|
|
16
16
|
#ActiveSupport::Deprecation.silenced = true
|
|
17
17
|
|
|
18
|
-
#
|
|
18
|
+
# Use a module to not pollute the global namespace
|
|
19
|
+
module CapybaraHelper
|
|
20
|
+
def self.register_driver(driver_name, args = [])
|
|
21
|
+
opts = { headless: true, js_errors: true, window_size: [1920, 1200], browser_options: {} }
|
|
22
|
+
args.each do |arg|
|
|
23
|
+
opts[:browser_options][arg] = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
Capybara.register_driver(driver_name) do |app|
|
|
27
|
+
Capybara::Cuprite::Driver.new(app, opts)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Register our own custom drivers
|
|
33
|
+
CapybaraHelper.register_driver(:headless_chrome, %w[disable-gpu no-sandbox disable-dev-shm-usage])
|
|
34
|
+
|
|
35
|
+
# Configure Capybara JS driver
|
|
36
|
+
Capybara.current_driver = :headless_chrome
|
|
37
|
+
Capybara.javascript_driver = :headless_chrome
|
|
38
|
+
|
|
39
|
+
# Configure Capybara server
|
|
40
|
+
Capybara.run_server = true
|
|
41
|
+
Capybara.server = :puma, { Silent: true }
|
|
19
42
|
|
|
20
43
|
class ActionDispatch::IntegrationTest
|
|
21
44
|
include Capybara::DSL
|
|
45
|
+
|
|
46
|
+
# What capybara calls a "page" in its DSL is actually a Capybara::Session
|
|
47
|
+
# and doesn't know about the *command* method that allows us to play with
|
|
48
|
+
# the Chrome API.
|
|
49
|
+
# See: https://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session
|
|
50
|
+
#
|
|
51
|
+
# To enable downloads we need to do it on the browser's page object, so fetch it
|
|
52
|
+
# from this long method chain.
|
|
53
|
+
# See: https://github.com/rubycdp/ferrum/blob/master/lib/ferrum/page.rb
|
|
54
|
+
def enable_chrome_headless_downloads(session, directory)
|
|
55
|
+
page = session.driver.browser.page
|
|
56
|
+
page.command('Page.setDownloadBehavior', behavior: 'allow', downloadPath: directory)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# From https://collectiveidea.com/blog/archives/2012/01/27/testing-file-downloads-with-capybara-and-chromedriver
|
|
61
|
+
module DownloadHelper
|
|
62
|
+
extend self
|
|
63
|
+
|
|
64
|
+
TIMEOUT = 10
|
|
65
|
+
|
|
66
|
+
def downloads
|
|
67
|
+
Dir["/tmp/devise-otp/*"]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def wait_for_download(count: 1)
|
|
71
|
+
yield if block_given?
|
|
72
|
+
|
|
73
|
+
Timeout.timeout(TIMEOUT) do
|
|
74
|
+
sleep 0.2 until downloaded?(count)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def downloaded?(count)
|
|
79
|
+
!downloading? && downloads.size == count
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def downloading?
|
|
83
|
+
downloads.grep(/\.crdownload$/).any?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def clear_downloads
|
|
87
|
+
FileUtils.rm_f(downloads)
|
|
88
|
+
end
|
|
22
89
|
end
|
|
90
|
+
|
|
91
|
+
require "devise-otp"
|
metadata
CHANGED
|
@@ -1,106 +1,210 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: devise-otp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lele Forzani
|
|
8
|
-
|
|
8
|
+
- Josef Strzibny
|
|
9
|
+
autorequire:
|
|
9
10
|
bindir: bin
|
|
10
11
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
+
date: 2022-03-19 00:00:00.000000000 Z
|
|
12
13
|
dependencies:
|
|
13
14
|
- !ruby/object:Gem::Dependency
|
|
14
15
|
name: rails
|
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
|
16
17
|
requirements:
|
|
17
|
-
- -
|
|
18
|
+
- - ">="
|
|
18
19
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
20
|
-
- - <
|
|
20
|
+
version: '7.0'
|
|
21
|
+
- - "<"
|
|
21
22
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: '
|
|
23
|
+
version: '7.1'
|
|
23
24
|
type: :runtime
|
|
24
25
|
prerelease: false
|
|
25
26
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
27
|
requirements:
|
|
27
|
-
- -
|
|
28
|
+
- - ">="
|
|
28
29
|
- !ruby/object:Gem::Version
|
|
29
|
-
version:
|
|
30
|
-
- - <
|
|
30
|
+
version: '7.0'
|
|
31
|
+
- - "<"
|
|
31
32
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
33
|
+
version: '7.1'
|
|
33
34
|
- !ruby/object:Gem::Dependency
|
|
34
35
|
name: devise
|
|
35
36
|
requirement: !ruby/object:Gem::Requirement
|
|
36
37
|
requirements:
|
|
37
|
-
- -
|
|
38
|
+
- - ">="
|
|
38
39
|
- !ruby/object:Gem::Version
|
|
39
|
-
version:
|
|
40
|
-
- - <
|
|
40
|
+
version: 4.8.0
|
|
41
|
+
- - "<"
|
|
41
42
|
- !ruby/object:Gem::Version
|
|
42
|
-
version: 4.
|
|
43
|
+
version: 4.9.0
|
|
43
44
|
type: :runtime
|
|
44
45
|
prerelease: false
|
|
45
46
|
version_requirements: !ruby/object:Gem::Requirement
|
|
46
47
|
requirements:
|
|
47
|
-
- -
|
|
48
|
+
- - ">="
|
|
48
49
|
- !ruby/object:Gem::Version
|
|
49
|
-
version:
|
|
50
|
-
- - <
|
|
50
|
+
version: 4.8.0
|
|
51
|
+
- - "<"
|
|
51
52
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: 4.
|
|
53
|
+
version: 4.9.0
|
|
53
54
|
- !ruby/object:Gem::Dependency
|
|
54
55
|
name: rotp
|
|
55
56
|
requirement: !ruby/object:Gem::Requirement
|
|
56
57
|
requirements:
|
|
57
|
-
- -
|
|
58
|
+
- - ">="
|
|
58
59
|
- !ruby/object:Gem::Version
|
|
59
60
|
version: 2.0.0
|
|
60
61
|
type: :runtime
|
|
61
62
|
prerelease: false
|
|
62
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
63
64
|
requirements:
|
|
64
|
-
- -
|
|
65
|
+
- - ">="
|
|
65
66
|
- !ruby/object:Gem::Version
|
|
66
67
|
version: 2.0.0
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: capybara
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: cuprite
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: minitest-reporters
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 0.5.0
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 0.5.0
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: puma
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
type: :development
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: rdoc
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0'
|
|
131
|
+
type: :development
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0'
|
|
138
|
+
- !ruby/object:Gem::Dependency
|
|
139
|
+
name: shoulda
|
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - ">="
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0'
|
|
145
|
+
type: :development
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - ">="
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0'
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: sprockets-rails
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - ">="
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '0'
|
|
159
|
+
type: :development
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - ">="
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '0'
|
|
67
166
|
- !ruby/object:Gem::Dependency
|
|
68
167
|
name: sqlite3
|
|
69
168
|
requirement: !ruby/object:Gem::Requirement
|
|
70
169
|
requirements:
|
|
71
|
-
- -
|
|
170
|
+
- - ">="
|
|
72
171
|
- !ruby/object:Gem::Version
|
|
73
172
|
version: '0'
|
|
74
173
|
type: :development
|
|
75
174
|
prerelease: false
|
|
76
175
|
version_requirements: !ruby/object:Gem::Requirement
|
|
77
176
|
requirements:
|
|
78
|
-
- -
|
|
177
|
+
- - ">="
|
|
79
178
|
- !ruby/object:Gem::Version
|
|
80
179
|
version: '0'
|
|
81
180
|
description: Time Based OTP/rfc6238 compatible authentication for Devise
|
|
82
181
|
email:
|
|
83
182
|
- lele@windmill.it
|
|
183
|
+
- strzibny@strzibny.name
|
|
84
184
|
executables: []
|
|
85
185
|
extensions: []
|
|
86
186
|
extra_rdoc_files: []
|
|
87
187
|
files:
|
|
88
|
-
- .
|
|
89
|
-
- .
|
|
188
|
+
- ".github/workflows/ci.yml"
|
|
189
|
+
- ".gitignore"
|
|
90
190
|
- Gemfile
|
|
91
191
|
- LICENSE.txt
|
|
92
192
|
- README.md
|
|
93
193
|
- Rakefile
|
|
94
|
-
- app/
|
|
95
|
-
- app/
|
|
96
|
-
- app/
|
|
97
|
-
- app/
|
|
98
|
-
- app/views/
|
|
99
|
-
- app/views/
|
|
100
|
-
- app/views/
|
|
101
|
-
- app/views/
|
|
194
|
+
- app/assets/javascripts/devise-otp.js
|
|
195
|
+
- app/assets/javascripts/qrcode.js
|
|
196
|
+
- app/controllers/devise_otp/devise/credentials_controller.rb
|
|
197
|
+
- app/controllers/devise_otp/devise/tokens_controller.rb
|
|
198
|
+
- app/views/devise/credentials/refresh.html.erb
|
|
199
|
+
- app/views/devise/credentials/show.html.erb
|
|
200
|
+
- app/views/devise/tokens/_token_secret.html.erb
|
|
201
|
+
- app/views/devise/tokens/_trusted_devices.html.erb
|
|
202
|
+
- app/views/devise/tokens/recovery.html.erb
|
|
203
|
+
- app/views/devise/tokens/recovery_codes.text.erb
|
|
204
|
+
- app/views/devise/tokens/show.html.erb
|
|
102
205
|
- config/locales/en.yml
|
|
103
206
|
- devise-otp.gemspec
|
|
207
|
+
- docs/QR_CODES.md
|
|
104
208
|
- lib/devise-otp.rb
|
|
105
209
|
- lib/devise-otp/version.rb
|
|
106
210
|
- lib/devise_otp_authenticatable/controllers/helpers.rb
|
|
@@ -108,7 +212,6 @@ files:
|
|
|
108
212
|
- lib/devise_otp_authenticatable/engine.rb
|
|
109
213
|
- lib/devise_otp_authenticatable/hooks.rb
|
|
110
214
|
- lib/devise_otp_authenticatable/hooks/sessions.rb
|
|
111
|
-
- lib/devise_otp_authenticatable/mapping.rb
|
|
112
215
|
- lib/devise_otp_authenticatable/models/otp_authenticatable.rb
|
|
113
216
|
- lib/devise_otp_authenticatable/routes.rb
|
|
114
217
|
- lib/generators/active_record/devise_otp_generator.rb
|
|
@@ -118,6 +221,7 @@ files:
|
|
|
118
221
|
- lib/generators/devise_otp/views_generator.rb
|
|
119
222
|
- test/dummy/README.rdoc
|
|
120
223
|
- test/dummy/Rakefile
|
|
224
|
+
- test/dummy/app/assets/config/manifest.js
|
|
121
225
|
- test/dummy/app/assets/javascripts/application.js
|
|
122
226
|
- test/dummy/app/assets/stylesheets/application.css
|
|
123
227
|
- test/dummy/app/controllers/application_controller.rb
|
|
@@ -154,6 +258,7 @@ files:
|
|
|
154
258
|
- test/dummy/db/migrate/20130131092406_add_devise_to_users.rb
|
|
155
259
|
- test/dummy/db/migrate/20130131142320_create_posts.rb
|
|
156
260
|
- test/dummy/db/migrate/20130131160351_devise_otp_add_to_users.rb
|
|
261
|
+
- test/dummy/db/test.sqlite3-journal
|
|
157
262
|
- test/dummy/lib/assets/.gitkeep
|
|
158
263
|
- test/dummy/public/404.html
|
|
159
264
|
- test/dummy/public/422.html
|
|
@@ -172,29 +277,29 @@ files:
|
|
|
172
277
|
homepage: http://git.windmill.it/wm/devise-otp
|
|
173
278
|
licenses: []
|
|
174
279
|
metadata: {}
|
|
175
|
-
post_install_message:
|
|
280
|
+
post_install_message:
|
|
176
281
|
rdoc_options: []
|
|
177
282
|
require_paths:
|
|
178
283
|
- lib
|
|
179
284
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
285
|
requirements:
|
|
181
|
-
- -
|
|
286
|
+
- - ">="
|
|
182
287
|
- !ruby/object:Gem::Version
|
|
183
288
|
version: '0'
|
|
184
289
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
290
|
requirements:
|
|
186
|
-
- -
|
|
291
|
+
- - ">="
|
|
187
292
|
- !ruby/object:Gem::Version
|
|
188
293
|
version: '0'
|
|
189
294
|
requirements: []
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
signing_key:
|
|
295
|
+
rubygems_version: 3.2.32
|
|
296
|
+
signing_key:
|
|
193
297
|
specification_version: 4
|
|
194
298
|
summary: Time Based OTP/rfc6238 compatible authentication for Devise
|
|
195
299
|
test_files:
|
|
196
300
|
- test/dummy/README.rdoc
|
|
197
301
|
- test/dummy/Rakefile
|
|
302
|
+
- test/dummy/app/assets/config/manifest.js
|
|
198
303
|
- test/dummy/app/assets/javascripts/application.js
|
|
199
304
|
- test/dummy/app/assets/stylesheets/application.css
|
|
200
305
|
- test/dummy/app/controllers/application_controller.rb
|
|
@@ -231,6 +336,7 @@ test_files:
|
|
|
231
336
|
- test/dummy/db/migrate/20130131092406_add_devise_to_users.rb
|
|
232
337
|
- test/dummy/db/migrate/20130131142320_create_posts.rb
|
|
233
338
|
- test/dummy/db/migrate/20130131160351_devise_otp_add_to_users.rb
|
|
339
|
+
- test/dummy/db/test.sqlite3-journal
|
|
234
340
|
- test/dummy/lib/assets/.gitkeep
|
|
235
341
|
- test/dummy/public/404.html
|
|
236
342
|
- test/dummy/public/422.html
|
data/.travis.yml
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
class DeviseOtp::CredentialsController < DeviseController
|
|
2
|
-
helper_method :new_session_path
|
|
3
|
-
|
|
4
|
-
prepend_before_filter :authenticate_scope!, :only => [:get_refresh, :set_refresh]
|
|
5
|
-
prepend_before_filter :require_no_authentication, :only => [ :show, :update ]
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
# show a request for the OTP token
|
|
9
|
-
#
|
|
10
|
-
def show
|
|
11
|
-
@challenge = params[:challenge]
|
|
12
|
-
@recovery = (params[:recovery] == 'true') && recovery_enabled?
|
|
13
|
-
|
|
14
|
-
if @challenge.nil?
|
|
15
|
-
redirect_to :root
|
|
16
|
-
|
|
17
|
-
else
|
|
18
|
-
self.resource = resource_class.find_valid_otp_challenge(@challenge)
|
|
19
|
-
if resource.nil?
|
|
20
|
-
redirect_to :root
|
|
21
|
-
elsif @recovery
|
|
22
|
-
@recovery_count = resource.otp_recovery_counter
|
|
23
|
-
render :show
|
|
24
|
-
else
|
|
25
|
-
render :show
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
#
|
|
31
|
-
# signs the resource in, if the OTP token is valid and the user has a valid challenge
|
|
32
|
-
#
|
|
33
|
-
def update
|
|
34
|
-
|
|
35
|
-
resource = resource_class.find_valid_otp_challenge(params[resource_name][:challenge])
|
|
36
|
-
recovery = (params[resource_name][:recovery] == 'true') && recovery_enabled?
|
|
37
|
-
token = params[resource_name][:token]
|
|
38
|
-
|
|
39
|
-
if token.blank?
|
|
40
|
-
otp_set_flash_message(:alert, :token_blank)
|
|
41
|
-
redirect_to otp_credential_path_for(resource_name, :challenge => params[resource_name][:challenge],
|
|
42
|
-
:recovery => recovery)
|
|
43
|
-
elsif resource.nil?
|
|
44
|
-
otp_set_flash_message(:alert, :otp_session_invalid)
|
|
45
|
-
redirect_to new_session_path(resource_name)
|
|
46
|
-
else
|
|
47
|
-
if resource.otp_challenge_valid? && resource.validate_otp_token(params[resource_name][:token], recovery)
|
|
48
|
-
set_flash_message(:success, :signed_in) if is_navigational_format?
|
|
49
|
-
sign_in(resource_name, resource)
|
|
50
|
-
|
|
51
|
-
otp_refresh_credentials_for(resource)
|
|
52
|
-
respond_with resource, :location => after_sign_in_path_for(resource)
|
|
53
|
-
else
|
|
54
|
-
otp_set_flash_message :alert, :token_invalid
|
|
55
|
-
redirect_to new_session_path(resource_name)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
#
|
|
62
|
-
# displays the request for a credentials refresh
|
|
63
|
-
#
|
|
64
|
-
def get_refresh
|
|
65
|
-
ensure_resource!
|
|
66
|
-
render :refresh
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
#
|
|
70
|
-
# lets the user through is the refresh is valid
|
|
71
|
-
#
|
|
72
|
-
def set_refresh
|
|
73
|
-
|
|
74
|
-
ensure_resource!
|
|
75
|
-
# I am sure there's a much better way
|
|
76
|
-
if resource.valid_password?(params[resource_name][:refresh_password])
|
|
77
|
-
if resource.otp_enabled?
|
|
78
|
-
if resource.validate_otp_token(params[resource_name][:token])
|
|
79
|
-
done_valid_refresh
|
|
80
|
-
else
|
|
81
|
-
failed_refresh
|
|
82
|
-
end
|
|
83
|
-
else
|
|
84
|
-
done_valid_refresh
|
|
85
|
-
end
|
|
86
|
-
else
|
|
87
|
-
failed_refresh
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
private
|
|
93
|
-
|
|
94
|
-
def done_valid_refresh
|
|
95
|
-
otp_refresh_credentials_for(resource)
|
|
96
|
-
otp_set_flash_message :success, :valid_refresh if is_navigational_format?
|
|
97
|
-
|
|
98
|
-
respond_with resource, :location => otp_fetch_refresh_return_url
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def failed_refresh
|
|
102
|
-
otp_set_flash_message :alert, :invalid_refresh
|
|
103
|
-
render :refresh
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
end
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
class DeviseOtp::TokensController < DeviseController
|
|
2
|
-
include Devise::Controllers::Helpers
|
|
3
|
-
|
|
4
|
-
prepend_before_filter :ensure_credentials_refresh
|
|
5
|
-
prepend_before_filter :authenticate_scope!
|
|
6
|
-
|
|
7
|
-
protect_from_forgery :except => [:clear_persistence, :delete_persistence]
|
|
8
|
-
|
|
9
|
-
#
|
|
10
|
-
# Displays the status of OTP authentication
|
|
11
|
-
#
|
|
12
|
-
def show
|
|
13
|
-
if resource.nil?
|
|
14
|
-
redirect_to stored_location_for(scope) || :root
|
|
15
|
-
else
|
|
16
|
-
render :show
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
#
|
|
21
|
-
# Updates the status of OTP authentication
|
|
22
|
-
#
|
|
23
|
-
def update
|
|
24
|
-
|
|
25
|
-
enabled = (params[resource_name][:otp_enabled] == '1')
|
|
26
|
-
if (enabled ? resource.enable_otp! : resource.disable_otp!)
|
|
27
|
-
|
|
28
|
-
otp_set_flash_message :success, :successfully_updated
|
|
29
|
-
end
|
|
30
|
-
render :show
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
#
|
|
34
|
-
# Resets OTP authentication, generates new credentials, sets it to off
|
|
35
|
-
#
|
|
36
|
-
def destroy
|
|
37
|
-
|
|
38
|
-
if resource.reset_otp_credentials!
|
|
39
|
-
otp_set_flash_message :success, :successfully_reset_creds
|
|
40
|
-
end
|
|
41
|
-
render :show
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
# makes the current browser persistent
|
|
47
|
-
#
|
|
48
|
-
def get_persistence
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if otp_set_trusted_device_for(resource)
|
|
52
|
-
otp_set_flash_message :success, :successfully_set_persistence
|
|
53
|
-
end
|
|
54
|
-
redirect_to :action => :show
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
#
|
|
59
|
-
# clears persistence for the current browser
|
|
60
|
-
#
|
|
61
|
-
def clear_persistence
|
|
62
|
-
if otp_clear_trusted_device_for(resource)
|
|
63
|
-
otp_set_flash_message :success, :successfully_cleared_persistence
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
redirect_to :action => :show
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
#
|
|
71
|
-
# rehash the persistence secret, thus, making all the persistence cookies invalid
|
|
72
|
-
#
|
|
73
|
-
def delete_persistence
|
|
74
|
-
if otp_reset_persistence_for(resource)
|
|
75
|
-
otp_set_flash_message :notice, :successfully_reset_persistence
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
redirect_to :action => :show
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
def recovery
|
|
85
|
-
render :recovery
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
private
|
|
90
|
-
|
|
91
|
-
def ensure_credentials_refresh
|
|
92
|
-
|
|
93
|
-
ensure_resource!
|
|
94
|
-
if needs_credentials_refresh?(resource)
|
|
95
|
-
otp_set_flash_message :notice, :need_to_refresh_credentials
|
|
96
|
-
redirect_to refresh_otp_credential_path_for(resource)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def scope
|
|
101
|
-
resource_name.to_sym
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<h2><%= I18n.t('title', {:scope => 'devise.otp.credentials_refresh'}) %></h2>
|
|
2
|
-
<p><%= I18n.t('explain', {:scope => 'devise.otp.credentials_refresh'}) %></p>
|
|
3
|
-
|
|
4
|
-
<%= form_for(resource, :as => resource_name, :url => [:refresh, resource_name, :otp_credential], :html => { :method => :put }) do |f| %>
|
|
5
|
-
|
|
6
|
-
<%= devise_error_messages! %>
|
|
7
|
-
|
|
8
|
-
<div><%= f.label :email %><br />
|
|
9
|
-
<%= f.text_field :email, :disabled => :true%></div>
|
|
10
|
-
|
|
11
|
-
<div><%= f.label :password %><br />
|
|
12
|
-
<%= f.password_field :refresh_password, :autocomplete => :off, :autofocus => true %></div>
|
|
13
|
-
|
|
14
|
-
<%- if resource.otp_enabled? %>
|
|
15
|
-
<div><%= f.label :token, I18n.t(:token, {:scope => 'devise.otp.credentials_refresh'}) %></p><br />
|
|
16
|
-
<%= f.password_field :token, :autocomplete => :off%></div>
|
|
17
|
-
<% end %>
|
|
18
|
-
|
|
19
|
-
<div><%= f.submit I18n.t(:go_on, {:scope => 'devise.otp.credentials_refresh'}) %></div>
|
|
20
|
-
<% end %>
|