devise-otp 0.2.2 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5936698b6e66c85c09d06f13df85acec3ef012b
4
- data.tar.gz: 88768f71081fa8385d38aa5c035453003f7253b4
3
+ metadata.gz: a79f472f1aa5f902585f4e0d9fba2be6acd49c4d
4
+ data.tar.gz: ae454d13216e89de407336b54572276958d1c7b6
5
5
  SHA512:
6
- metadata.gz: b7f176ffae7d15974ce50a6e60c9a169c6e03c5e0f9933b7642e893592d4691c3e7d561a7755ea011a246d7a02a6711aa9c3e0b0cd0a75de1c5312126d94b2ea
7
- data.tar.gz: d1c47a4ce461d627709639a76963130b3566dda2951a2685d40551dccdad204d68ab15f0606ba31da9ba40259ceccfb21fe68bd2a3b32158292d092591a73ff7
6
+ metadata.gz: 850c7c8ce55daf8a956f5d281f3e3be67030c543f7d91872e1009216c57f5dc8e56a381f287b862c1b994117a06fe5fc836829b3dc759c9ce12564c2743bb711
7
+ data.tar.gz: 425351d1ac147a529daf7a45d07456f8bc49697134ecaf6495bb42100f2b5cc451720620d461291fbdcde4c3b8e70cb61eb4b31d192cbabdd28f637883e7df5d
@@ -1,5 +1,5 @@
1
1
  module Devise
2
2
  module Otp
3
- VERSION = "0.2.2"
3
+ VERSION = "0.2.3"
4
4
  end
5
5
  end
@@ -74,8 +74,7 @@ module DeviseOtpAuthenticatable
74
74
  return false unless resource.class.otp_trust_persistence
75
75
  if cookies[otp_scoped_persistence_cookie].present?
76
76
  cookies.signed[otp_scoped_persistence_cookie] ==
77
- [resource.class.serialize_into_cookie(resource), resource.otp_persistence_seed].tap do
78
- end
77
+ [resource.to_key, resource.authenticatable_salt, resource.otp_persistence_seed]
79
78
  else
80
79
  false
81
80
  end
@@ -89,7 +88,7 @@ module DeviseOtpAuthenticatable
89
88
  cookies.signed[otp_scoped_persistence_cookie] = {
90
89
  :httponly => true,
91
90
  :expires => Time.now + resource.class.otp_trust_persistence,
92
- :value => [resource.class.serialize_into_cookie(resource), resource.otp_persistence_seed]
91
+ :value => [resource.to_key, resource.authenticatable_salt, resource.otp_persistence_seed]
93
92
  }
94
93
  end
95
94
 
@@ -41,7 +41,7 @@ module Devise::Models
41
41
  @recovery_otp = nil
42
42
  generate_otp_auth_secret
43
43
  reset_otp_persistence
44
- update(:otp_enabled => false, :otp_time_drift => 0,
44
+ update_attributes!(:otp_enabled => false, :otp_time_drift => 0,
45
45
  :otp_session_challenge => nil, :otp_challenge_expires => nil,
46
46
  :otp_recovery_counter => 0)
47
47
  end
@@ -61,15 +61,15 @@ module Devise::Models
61
61
  end
62
62
 
63
63
  def enable_otp!
64
- update!(:otp_enabled => true, :otp_enabled_on => Time.now)
64
+ update_attributes!(:otp_enabled => true, :otp_enabled_on => Time.now)
65
65
  end
66
66
 
67
67
  def disable_otp!
68
- update!(:otp_enabled => false, :otp_enabled_on => nil, :otp_time_drift => 0)
68
+ update_attributes!(:otp_enabled => false, :otp_enabled_on => nil, :otp_time_drift => 0)
69
69
  end
70
70
 
71
71
  def generate_otp_challenge!(expires = nil)
72
- update!(:otp_session_challenge => SecureRandom.hex,
72
+ update_attributes!(:otp_session_challenge => SecureRandom.hex,
73
73
  :otp_challenge_expires => DateTime.now + (expires || self.class.otp_authentication_timeout))
74
74
  otp_session_challenge
75
75
  end
@@ -89,12 +89,8 @@ module Devise::Models
89
89
  alias_method :valid_otp_token?, :validate_otp_token
90
90
 
91
91
  def validate_otp_time_token(token)
92
- if drift = validate_otp_token_with_drift(token)
93
- update_column(:otp_time_drift, drift)
94
- true
95
- else
96
- false
97
- end
92
+ return false if token.blank?
93
+ validate_otp_token_with_drift(token)
98
94
  end
99
95
  alias_method :valid_otp_time_token?, :validate_otp_time_token
100
96
 
@@ -12,7 +12,7 @@ class User < PARENT_MODEL_CLASS
12
12
  end
13
13
 
14
14
  devise :otp_authenticatable, :database_authenticatable, :registerable,
15
- :recoverable, :rememberable, :trackable, :validatable
15
+ :trackable, :validatable
16
16
 
17
17
  # Setup accessible (or protected) attributes for your model
18
18
  #attr_accessible :otp_enabled, :otp_mandatory, :as => :otp_privileged
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+ require 'integration_tests_helper'
3
+
4
+ class PersistenceTest < ActionDispatch::IntegrationTest
5
+
6
+ def setup
7
+ @old_persistence = User.otp_trust_persistence
8
+ User.otp_trust_persistence = 3.seconds
9
+ end
10
+
11
+ def teardown
12
+ User.otp_trust_persistence = @old_persistence
13
+ Capybara.reset_sessions!
14
+ end
15
+
16
+ test 'a user should be requested the otp challenge every log in' do
17
+ # log in 1fa
18
+ user = enable_otp_and_sign_in
19
+ otp_challenge_for user
20
+
21
+ visit user_otp_token_path
22
+ assert_equal user_otp_token_path, current_path
23
+
24
+ sign_out
25
+ sign_user_in
26
+
27
+ assert_equal user_otp_credential_path, current_path
28
+ end
29
+
30
+ test 'a user should be able to set their browser as trusted' do
31
+ # log in 1fa
32
+ user = enable_otp_and_sign_in
33
+ otp_challenge_for user
34
+
35
+ visit user_otp_token_path
36
+ assert_equal user_otp_token_path, current_path
37
+
38
+ click_link('Trust this browser')
39
+ assert_text 'Your browser is trusted.'
40
+ sign_out
41
+
42
+ sign_user_in
43
+
44
+ assert_equal root_path, current_path
45
+ end
46
+
47
+ test 'trusted status should expire' do
48
+ # log in 1fa
49
+ user = enable_otp_and_sign_in
50
+ otp_challenge_for user
51
+
52
+ visit user_otp_token_path
53
+ assert_equal user_otp_token_path, current_path
54
+
55
+ click_link('Trust this browser')
56
+ assert_text 'Your browser is trusted.'
57
+ sign_out
58
+
59
+ sleep User.otp_trust_persistence.to_i + 1
60
+ sign_user_in
61
+
62
+ assert_equal user_otp_credential_path, current_path
63
+ end
64
+
65
+ end
@@ -89,4 +89,18 @@ class RefreshTest < ActionDispatch::IntegrationTest
89
89
 
90
90
  assert_equal user_otp_token_path, current_path
91
91
  end
92
+
93
+ test 'and rejected when the token is blank or null' do
94
+ user = enable_otp_and_sign_in_with_otp
95
+
96
+ sleep(2)
97
+ visit user_otp_token_path
98
+ assert_equal refresh_user_otp_credential_path, current_path
99
+
100
+ fill_in 'user_refresh_password', :with => '12345678'
101
+ fill_in 'user_token', :with => ''
102
+ click_button 'Continue...'
103
+
104
+ assert_equal refresh_user_otp_credential_path, current_path
105
+ end
92
106
  end
@@ -50,6 +50,16 @@ class SignInTest < ActionDispatch::IntegrationTest
50
50
  assert_equal new_user_session_path, current_path
51
51
  end
52
52
 
53
+ test 'fail blank token authentication' do
54
+ enable_otp_and_sign_in
55
+ assert_equal user_otp_credential_path, current_path
56
+
57
+ fill_in 'user_token', :with => ''
58
+ click_button 'Submit Token'
59
+
60
+ assert_equal user_otp_credential_path, current_path
61
+ end
62
+
53
63
  test 'successful token authentication' do
54
64
  user = enable_otp_and_sign_in
55
65
 
@@ -1,4 +1,5 @@
1
1
  class ActionDispatch::IntegrationTest
2
+ include Warden::Test::Helpers
2
3
 
3
4
  def warden
4
5
  request.env['warden']
@@ -36,6 +37,11 @@ class ActionDispatch::IntegrationTest
36
37
  user
37
38
  end
38
39
 
40
+ def otp_challenge_for(user)
41
+ fill_in 'user_token', :with => ROTP::TOTP.new(user.otp_auth_secret).at(Time.now)
42
+ click_button 'Submit Token'
43
+ end
44
+
39
45
  def disable_otp
40
46
  visit user_otp_token_path
41
47
  uncheck 'user_otp_enabled'
@@ -43,7 +49,7 @@ class ActionDispatch::IntegrationTest
43
49
  end
44
50
 
45
51
  def sign_out
46
- Capybara.reset_sessions!
52
+ logout :user
47
53
  end
48
54
 
49
55
  def sign_user_in(user = nil)
@@ -57,5 +63,4 @@ class ActionDispatch::IntegrationTest
57
63
  user
58
64
  end
59
65
 
60
-
61
66
  end
@@ -80,6 +80,12 @@ class OtpAuthenticatableTest < ActiveSupport::TestCase
80
80
  assert_equal false, u.otp_challenge_valid?
81
81
  end
82
82
 
83
+ test 'null otp challenge' do
84
+ u = User.first
85
+ u.update_attribute(:otp_enabled, true)
86
+ assert_equal false, u.validate_otp_token('')
87
+ assert_equal false, u.validate_otp_token(nil)
88
+ end
83
89
 
84
90
  test 'generated otp token should be valid for the user' do
85
91
  u = User.first
metadata CHANGED
@@ -1,81 +1,81 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise-otp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lele Forzani
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-14 00:00:00.000000000 Z
11
+ date: 2014-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.2.6
20
- - - "<"
20
+ - - <
21
21
  - !ruby/object:Gem::Version
22
22
  version: '5'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ">="
27
+ - - '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: 3.2.6
30
- - - "<"
30
+ - - <
31
31
  - !ruby/object:Gem::Version
32
32
  version: '5'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: devise
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ">="
37
+ - - '>='
38
38
  - !ruby/object:Gem::Version
39
39
  version: 3.1.0
40
- - - "<"
40
+ - - <
41
41
  - !ruby/object:Gem::Version
42
42
  version: 4.0.0
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ">="
47
+ - - '>='
48
48
  - !ruby/object:Gem::Version
49
49
  version: 3.1.0
50
- - - "<"
50
+ - - <
51
51
  - !ruby/object:Gem::Version
52
52
  version: 4.0.0
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: rotp
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
- - - ">="
57
+ - - '>='
58
58
  - !ruby/object:Gem::Version
59
59
  version: 2.0.0
60
60
  type: :runtime
61
61
  prerelease: false
62
62
  version_requirements: !ruby/object:Gem::Requirement
63
63
  requirements:
64
- - - ">="
64
+ - - '>='
65
65
  - !ruby/object:Gem::Version
66
66
  version: 2.0.0
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: sqlite3
69
69
  requirement: !ruby/object:Gem::Requirement
70
70
  requirements:
71
- - - ">="
71
+ - - '>='
72
72
  - !ruby/object:Gem::Version
73
73
  version: '0'
74
74
  type: :development
75
75
  prerelease: false
76
76
  version_requirements: !ruby/object:Gem::Requirement
77
77
  requirements:
78
- - - ">="
78
+ - - '>='
79
79
  - !ruby/object:Gem::Version
80
80
  version: '0'
81
81
  description: Time Based OTP/rfc6238 compatible authentication for Devise
@@ -85,8 +85,8 @@ executables: []
85
85
  extensions: []
86
86
  extra_rdoc_files: []
87
87
  files:
88
- - ".gitignore"
89
- - ".travis.yml"
88
+ - .gitignore
89
+ - .travis.yml
90
90
  - Gemfile
91
91
  - LICENSE.txt
92
92
  - README.md
@@ -160,6 +160,7 @@ files:
160
160
  - test/dummy/public/500.html
161
161
  - test/dummy/public/favicon.ico
162
162
  - test/dummy/script/rails
163
+ - test/integration/persistence_test.rb
163
164
  - test/integration/refresh_test.rb
164
165
  - test/integration/sign_in_test.rb
165
166
  - test/integration/token_test.rb
@@ -177,12 +178,12 @@ require_paths:
177
178
  - lib
178
179
  required_ruby_version: !ruby/object:Gem::Requirement
179
180
  requirements:
180
- - - ">="
181
+ - - '>='
181
182
  - !ruby/object:Gem::Version
182
183
  version: '0'
183
184
  required_rubygems_version: !ruby/object:Gem::Requirement
184
185
  requirements:
185
- - - ">="
186
+ - - '>='
186
187
  - !ruby/object:Gem::Version
187
188
  version: '0'
188
189
  requirements: []
@@ -236,6 +237,7 @@ test_files:
236
237
  - test/dummy/public/500.html
237
238
  - test/dummy/public/favicon.ico
238
239
  - test/dummy/script/rails
240
+ - test/integration/persistence_test.rb
239
241
  - test/integration/refresh_test.rb
240
242
  - test/integration/sign_in_test.rb
241
243
  - test/integration/token_test.rb