devise-otp 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68e7b6bff6340dae80c51a03b25daa473524eee4
4
- data.tar.gz: 1407a2855ebf8bd2df27e678bf1b360922e894eb
3
+ metadata.gz: b5936698b6e66c85c09d06f13df85acec3ef012b
4
+ data.tar.gz: 88768f71081fa8385d38aa5c035453003f7253b4
5
5
  SHA512:
6
- metadata.gz: 4f233eb0d98a0ec858a27711f355d7ab6306d358b0f0ea80008616c06904ad917b7becfe6f988f51b930627bb6126fa8cc3d23e73b2deb8588fe10d2e963a454
7
- data.tar.gz: fab7310046129c7f095493f0505a3b1b16906608165f0ee446c6afc3980b34e9a0683da2553ac9cec7c80baa409a09305b7abd68c985e4d397384a9d57471a38
6
+ metadata.gz: b7f176ffae7d15974ce50a6e60c9a169c6e03c5e0f9933b7642e893592d4691c3e7d561a7755ea011a246d7a02a6711aa9c3e0b0cd0a75de1c5312126d94b2ea
7
+ data.tar.gz: d1c47a4ce461d627709639a76963130b3566dda2951a2685d40551dccdad204d68ab15f0606ba31da9ba40259ceccfb21fe68bd2a3b32158292d092591a73ff7
@@ -2,6 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1.2
5
6
  - rbx-19mode
6
7
  - rbx-20mode
7
8
  script: rake test
data/README.md CHANGED
@@ -4,16 +4,19 @@
4
4
  Devise OTP implements two-factors authentication for Devise, using an rfc6238 compatible Time-Based One-Time Password Algorithm.
5
5
  It uses the [rotp library](https://github.com/mdp/rotp) for generation and verification of codes.
6
6
 
7
+ **If you are upgrading from version 0.1.x, you will need to regenerate your views.**
8
+
7
9
  It currently has the following features:
8
10
 
9
11
  * Url based provisioning of token devices, compatible with **Google Authenticator**.
10
- * Two factors authentication can be **optional** at user discretion, **recommended** (it nags the user on every sign-in) or **mandatory** (users must enroll OTP after signing-in next time, before they can navigate the site). The settings is global, or per-user.
12
+ * Browsers can be set as 'trusted' for a limited time. During that time no OTP challenge is asked again when logging from that browser (but normal login will).
13
+ * Two factors authentication can be **optional** at user discretion, **recommended** (it nags the user on every sign-in) or **mandatory** (users must enroll OTP after signing-in next time, before they can navigate the site). The settings is global, or per-user. ( **incomplete**, see below)
11
14
  * Optionally, users can obtain a list of HOTP recovery tokens to be used for emergency log-in in case the token device is lost or unavailable.
12
15
 
13
16
  Compatible token devices are:
14
17
 
15
18
  * [Google Authenticator](https://code.google.com/p/google-authenticator/)
16
- * ...
19
+ * [FreeOTP](https://fedorahosted.org/freeotp/)
17
20
 
18
21
  ## Quick overview of Two Factors Authentication, using OTPs.
19
22
 
@@ -99,12 +102,19 @@ With this extension enabled, the following is expected behaviour:
99
102
 
100
103
  The install generator adds some options to the end of your Devise config file (config/initializers/devise.rb)
101
104
 
102
- * config.otp_mandatory - OTP is mandatory, users are going to be asked to enroll the next time they sign in, before they can successfully complete the session establishment.
103
- * config.otp_authentication_timeout - how long the user has to authenticate with their token. (defaults to 3.minutes)s
104
- * config.otp_drift_window - a window which provides allowance for drift between a user's token device clock (and therefore their OTP tokens) and the authentication server's clock. (default: 3)
105
- * config.otp_credentials_refresh - Users that have logged in longer than this time ago, or haven't refreshed, are boing to be asked their password (and an OTP token, if enabled) before they can see or change their otp informations. (defaults to 15.minutes)
106
- * config.recovery_tokens - Whether the users are given a list of one-time recovery tokens, for emergency access (default: true)
107
- * config.otp_uri_application - The name of this application, to be added to the provisioning url as '<user_email>/application_name' (defaults to the Rails application class)
105
+ * `config.otp_mandatory` - OTP is mandatory, users are going to be asked to enroll the next time they sign in, before they can successfully complete the session establishment.
106
+ * `config.otp_authentication_timeout` - how long the user has to authenticate with their token. (defaults to `3.minutes`)
107
+ * `config.otp_drift_window` - a window which provides allowance for drift between a user's token device clock (and therefore their OTP tokens) and the authentication server's clock. Expressed in minutes centered at the current time. (default: `3`)
108
+ * `config.otp_credentials_refresh` - Users that have logged in longer than this time ago, are going to be asked their password (and an OTP challenge, if enabled) before they can see or change their otp informations. (defaults to `15.minutes`)
109
+ * `config.otp_recovery_tokens` - Whether the users are given a list of one-time recovery tokens, for emergency access (default: `10`, set to `false` to disable)
110
+ * `config.otp_trust_persistence` - The user is allowed to set his browser as "trusted", no more OTP challenges will be asked for that browser, for a limited time. (default: `1.month`, set to false to disable setting the browser as trusted)
111
+ * `config.otp_uri_application` - The name of this application, to be added to the provisioning url as '<user_email>/application_name' (defaults to the Rails application class)
112
+
113
+ ## Todo
114
+
115
+ * 2D barcodes for provisioning are currently produced with the google charts api. You can, of course, use your own source in the template, but I am looking for a solution with no external dependencies (feedback welcome).
116
+ * **recommended** mode (nag the user each time) is not fully implemented. Right now you can make 2FA mandatory, or leave it to the user.
117
+
108
118
 
109
119
  ## Contributing
110
120
 
@@ -4,7 +4,7 @@ class DeviseOtp::TokensController < DeviseController
4
4
  prepend_before_filter :ensure_credentials_refresh
5
5
  prepend_before_filter :authenticate_scope!
6
6
 
7
- #protect_from_forgery :except => [:clear_persistence, :delete_persistence]
7
+ protect_from_forgery :except => [:clear_persistence, :delete_persistence]
8
8
 
9
9
  #
10
10
  # Displays the status of OTP authentication
@@ -21,14 +21,13 @@ class DeviseOtp::TokensController < DeviseController
21
21
  # Updates the status of OTP authentication
22
22
  #
23
23
  def update
24
- #if resource.update_without_password(params[resource_name])
25
- if resource.update_attribute(:otp_enabled, params[resource_name][:otp_enabled])
24
+
25
+ enabled = (params[resource_name][:otp_enabled] == '1')
26
+ if (enabled ? resource.enable_otp! : resource.disable_otp!)
26
27
 
27
28
  otp_set_flash_message :success, :successfully_updated
28
- render :show
29
- else
30
- render :show
31
29
  end
30
+ render :show
32
31
  end
33
32
 
34
33
  #
@@ -86,6 +85,7 @@ class DeviseOtp::TokensController < DeviseController
86
85
  render :recovery
87
86
  end
88
87
 
88
+
89
89
  private
90
90
 
91
91
  def ensure_credentials_refresh
@@ -17,7 +17,7 @@
17
17
  </p>
18
18
 
19
19
  <p><%= f.submit I18n.t('submit', {:scope => 'devise.otp.submit_token'}) %></p>
20
- <%- if !@recovery && resource_class.recovery_tokens %>
20
+ <%- if !@recovery && recovery_enabled? %>
21
21
  <p><%= link_to I18n.t('recovery_link', {:scope => 'devise.otp.submit_token'}), otp_credential_path_for(resource_name, :challenge => @challenge, :recovery => true) %></p>
22
22
  <% end %>
23
23
  <% end %>
@@ -0,0 +1,10 @@
1
+ <h3><%= I18n.t('title', {:scope => 'devise.otp.trusted_devices'}) %></h3>
2
+ <p><%= I18n.t('explain', {:scope => 'devise.otp.trusted_devices'}) %></p>
3
+ <%- if is_otp_trusted_device_for? resource %>
4
+ <p><em><%= I18n.t('device_trusted', {:scope => 'devise.otp.trusted_devices'}) %></em></p>
5
+ <p><%= link_to I18n.t('trust_remove', {:scope => 'devise.otp.trusted_devices'}), persistence_otp_token_path_for(resource_name), :method => :post %></p>
6
+ <% else %>
7
+ <p><%= I18n.t('device_not_trusted', {:scope => 'devise.otp.trusted_devices'}) %></p>
8
+ <p><%= link_to I18n.t('trust_add', {:scope => 'devise.otp.trusted_devices'}), persistence_otp_token_path_for(resource_name) %></p>
9
+ <% end %>
10
+ <p><%= link_to I18n.t('trust_clear', {:scope => 'devise.otp.trusted_devices'}), persistence_otp_token_path_for(resource_name), :method => :delete %></p>
@@ -1,6 +1,4 @@
1
1
  <h2><%= I18n.t('title', {:scope => 'devise.otp.tokens'}) %></h2>
2
- <p><%= I18n.t('caption', {:scope => 'devise.otp.tokens'}) %></p>
3
-
4
2
  <p><%= I18n.t('explain', {:scope => 'devise.otp.tokens'}) %></p>
5
3
 
6
4
  <%= form_for(resource, :as => resource_name, :url => [resource_name, :otp_token], :html => { :method => :put }) do |f| %>
@@ -17,15 +15,5 @@
17
15
 
18
16
  <%- if resource.otp_enabled? %>
19
17
  <%= render :partial => 'token_secret' if resource.otp_enabled? %>
20
-
21
- <h3><%= I18n.t('title', {:scope => 'devise.otp.trusted_devices'}) %></h3>
22
- <p><%= I18n.t('explain', {:scope => 'devise.otp.trusted_devices'}) %></p>
23
- <%- if is_otp_trusted_device_for? resource %>
24
- <p><em><%= I18n.t('device_trusted', {:scope => 'devise.otp.trusted_devices'}) %></em></p>
25
- <p><%= link_to I18n.t('trust_remove', {:scope => 'devise.otp.trusted_devices'}), persistence_otp_token_path_for(resource_name), :method => :post %></p>
26
- <% else %>
27
- <p><%= I18n.t('device_not_trusted', {:scope => 'devise.otp.trusted_devices'}) %></p>
28
- <p><%= link_to I18n.t('trust_add', {:scope => 'devise.otp.trusted_devices'}), persistence_otp_token_path_for(resource_name) %></p>
29
- <% end %>
30
- <p><%= link_to I18n.t('trust_clear', {:scope => 'devise.otp.trusted_devices'}), persistence_otp_token_path_for(resource_name), :method => :delete %></p>
18
+ <%= render :partial => 'trusted_devices' if trusted_devices_enabled? %>
31
19
  <% end %>
@@ -34,7 +34,7 @@ en:
34
34
 
35
35
  tokens:
36
36
  title: 'Two-factors Authentication:'
37
- explain: 'Two factors does this and that and that also'
37
+ explain: 'Two factors authentication adds adds an additional layer of security to your account. When logging in you will be asked for a code that you can generate on a physical device, like your phone.'
38
38
  enable_request: 'Would you like to enable Two Factors Authenticator?'
39
39
 
40
40
  status: 'Enable Two-Factors Authentication.'
@@ -57,10 +57,10 @@ en:
57
57
 
58
58
 
59
59
  trusted_devices:
60
- title: 'Trusted Devices'
61
- explain: 'Trusted Device are ....'
62
- device_trusted: 'Your device is trusted.'
63
- device_not_trusted: 'Your device is not trusted.'
64
- trust_remove: 'Remove this device from the list of trusted devices'
65
- trust_add: 'Trust this device'
66
- trust_clear: 'Clear the list of trusted devices'
60
+ title: 'Trusted Browsers'
61
+ explain: 'If you set your browser as trusted, you will not be asked to perform a 2-factors authentication when logging in from that browser, for a time of one month.'
62
+ device_trusted: 'Your browser is trusted.'
63
+ device_not_trusted: 'Your browser is not trusted.'
64
+ trust_remove: 'Remove this device from the list of trusted browsers'
65
+ trust_add: 'Trust this browser'
66
+ trust_clear: 'Clear the list of trusted browser'
@@ -28,14 +28,21 @@ module Devise
28
28
  #
29
29
  #
30
30
  #
31
- mattr_accessor :recovery_tokens
32
- @@recovery_tokens = 5 ## false to disable
31
+ mattr_accessor :otp_recovery_tokens
32
+ @@otp_recovery_tokens = 10 ## false to disable
33
+
34
+ #
35
+ # If the user is given the chance to set his browser as trusted, how long will it stay trusted.
36
+ # set to nil/false to disable the ability to set a device as trusted
37
+ #
38
+ mattr_accessor :otp_trust_persistence
39
+ @@otp_trust_persistence = 30.days
33
40
 
34
41
  #
35
42
  #
36
43
  #
37
44
  mattr_accessor :otp_drift_window
38
- @@otp_drift_window = 3 # in seconds
45
+ @@otp_drift_window = 3 # in minutes
39
46
 
40
47
  #
41
48
  # if the user wants to change Otp settings,
@@ -1,5 +1,5 @@
1
1
  module Devise
2
2
  module Otp
3
- VERSION = "0.2.0"
3
+ VERSION = "0.2.2"
4
4
  end
5
5
  end
@@ -27,8 +27,12 @@ module DeviseOtpAuthenticatable
27
27
  end
28
28
 
29
29
 
30
+ def trusted_devices_enabled?
31
+ resource.class.otp_trust_persistence && (resource.class.otp_trust_persistence > 0)
32
+ end
33
+
30
34
  def recovery_enabled?
31
- resource_class.recovery_tokens && (resource_class.recovery_tokens > 0)
35
+ resource_class.otp_recovery_tokens && (resource_class.otp_recovery_tokens > 0)
32
36
  end
33
37
 
34
38
  #
@@ -67,6 +71,7 @@ module DeviseOtpAuthenticatable
67
71
  # is the current browser trusted?
68
72
  #
69
73
  def is_otp_trusted_device_for?(resource)
74
+ return false unless resource.class.otp_trust_persistence
70
75
  if cookies[otp_scoped_persistence_cookie].present?
71
76
  cookies.signed[otp_scoped_persistence_cookie] ==
72
77
  [resource.class.serialize_into_cookie(resource), resource.otp_persistence_seed].tap do
@@ -80,9 +85,10 @@ module DeviseOtpAuthenticatable
80
85
  # make the current browser trusted
81
86
  #
82
87
  def otp_set_trusted_device_for(resource)
88
+ return unless resource.class.otp_trust_persistence
83
89
  cookies.signed[otp_scoped_persistence_cookie] = {
84
90
  :httponly => true,
85
- :expires => 30.days.from_now,
91
+ :expires => Time.now + resource.class.otp_trust_persistence,
86
92
  :value => [resource.class.serialize_into_cookie(resource), resource.otp_persistence_seed]
87
93
  }
88
94
  end
@@ -3,13 +3,11 @@ module DeviseOtpAuthenticatable
3
3
 
4
4
  module UrlHelpers
5
5
 
6
-
7
6
  def recovery_otp_token_for(resource_or_scope, opts = {})
8
7
  scope = Devise::Mapping.find_scope!(resource_or_scope)
9
8
  send("recovery_#{scope}_otp_token_path", opts)
10
9
  end
11
10
 
12
-
13
11
  def refresh_otp_credential_path_for(resource_or_scope, opts = {})
14
12
  scope = Devise::Mapping.find_scope!(resource_or_scope)
15
13
  send("refresh_#{scope}_otp_credential_path", opts)
@@ -11,8 +11,8 @@ module Devise::Models
11
11
  end
12
12
 
13
13
  module ClassMethods
14
- ::Devise::Models.config(self, :otp_authentication_timeout, :otp_drift_window,
15
- :otp_mandatory, :otp_credentials_refresh, :otp_uri_application, :recovery_tokens)
14
+ ::Devise::Models.config(self, :otp_authentication_timeout, :otp_drift_window, :otp_trust_persistence,
15
+ :otp_mandatory, :otp_credentials_refresh, :otp_uri_application, :otp_recovery_tokens)
16
16
 
17
17
  def find_valid_otp_challenge(challenge)
18
18
  with_valid_otp_challenge(Time.now).where(:otp_session_challenge => challenge).first
@@ -41,9 +41,9 @@ module Devise::Models
41
41
  @recovery_otp = nil
42
42
  generate_otp_auth_secret
43
43
  reset_otp_persistence
44
- update_columns(:otp_enabled => false, :otp_time_drift => 0,
45
- :otp_session_challenge => nil, :otp_challenge_expires => nil,
46
- :otp_recovery_counter => 0)
44
+ update(:otp_enabled => false, :otp_time_drift => 0,
45
+ :otp_session_challenge => nil, :otp_challenge_expires => nil,
46
+ :otp_recovery_counter => 0)
47
47
  end
48
48
 
49
49
  def reset_otp_credentials!
@@ -51,7 +51,6 @@ module Devise::Models
51
51
  save!
52
52
  end
53
53
 
54
-
55
54
  def reset_otp_persistence
56
55
  generate_otp_persistence_seed
57
56
  end
@@ -61,9 +60,17 @@ module Devise::Models
61
60
  save!
62
61
  end
63
62
 
63
+ def enable_otp!
64
+ update!(:otp_enabled => true, :otp_enabled_on => Time.now)
65
+ end
66
+
67
+ def disable_otp!
68
+ update!(:otp_enabled => false, :otp_enabled_on => nil, :otp_time_drift => 0)
69
+ end
70
+
64
71
  def generate_otp_challenge!(expires = nil)
65
- update_columns(:otp_session_challenge => SecureRandom.hex,
66
- :otp_challenge_expires => DateTime.now + (expires || self.class.otp_authentication_timeout))
72
+ update!(:otp_session_challenge => SecureRandom.hex,
73
+ :otp_challenge_expires => DateTime.now + (expires || self.class.otp_authentication_timeout))
67
74
  otp_session_challenge
68
75
  end
69
76
 
@@ -91,7 +98,7 @@ module Devise::Models
91
98
  end
92
99
  alias_method :valid_otp_time_token?, :validate_otp_time_token
93
100
 
94
- def next_otp_recovery_tokens(number = 5)
101
+ def next_otp_recovery_tokens(number = self.class.otp_recovery_tokens)
95
102
  (otp_recovery_counter..otp_recovery_counter + number).inject({}) do |h, index|
96
103
  h[index] = recovery_otp.at(index)
97
104
  h
@@ -108,21 +115,13 @@ module Devise::Models
108
115
 
109
116
 
110
117
 
111
-
112
-
113
118
  private
114
119
 
115
- #
116
- # refactor me, I suck
117
- #
118
120
  def validate_otp_token_with_drift(token)
119
- # valid_vals << ROTP::TOTP.new(otp_auth_secret).at(Time.now)
120
121
 
121
122
  # should be centered around saved drift
122
- (-self.class.otp_drift_window..self.class.otp_drift_window).each do |drift|
123
- return drift if(time_based_otp.verify(token, Time.now.ago(30 * drift)))
124
- end
125
- false
123
+ (-self.class.otp_drift_window..self.class.otp_drift_window).any? {|drift|
124
+ (time_based_otp.verify(token, Time.now.ago(30 * drift))) }
126
125
  end
127
126
 
128
127
  def generate_otp_persistence_seed
@@ -11,9 +11,11 @@ module ActionDispatch::Routing
11
11
  resource :token, :only => [:show, :update, :destroy],
12
12
  :path => mapping.path_names[:token], :controller => controllers[:otp_tokens] do
13
13
 
14
- get :persistence, :action => 'get_persistence'
15
- post :persistence, :action => 'clear_persistence'
16
- delete :persistence, :action => 'delete_persistence'
14
+ if Devise.otp_trust_persistence
15
+ get :persistence, :action => 'get_persistence'
16
+ post :persistence, :action => 'clear_persistence'
17
+ delete :persistence, :action => 'delete_persistence'
18
+ end
17
19
 
18
20
  get :recovery
19
21
  end
@@ -6,7 +6,7 @@ module ActiveRecord
6
6
  source_root File.expand_path("../templates", __FILE__)
7
7
 
8
8
  def copy_devise_migration
9
- migration_template "migration.rb", "db/migrate/devise_otp_add_to_#{table_name}"
9
+ migration_template "migration.rb", "db/migrate/devise_otp_add_to_#{table_name}.rb"
10
10
  end
11
11
  end
12
12
  end
@@ -6,7 +6,6 @@ class DeviseOtpAddTo<%= table_name.camelize %> < ActiveRecord::Migration
6
6
  t.boolean :otp_enabled, :default => false, :null => false
7
7
  t.boolean :otp_mandatory, :default => false, :null => false
8
8
  t.datetime :otp_enabled_on
9
- t.integer :otp_time_drift, :default => 0, :null => false
10
9
  t.integer :otp_failed_attempts, :default => 0, :null => false
11
10
  t.integer :otp_recovery_counter, :default => 0, :null => false
12
11
  t.string :otp_persistence_seed
@@ -13,11 +13,33 @@ content = <<-CONTENT
13
13
  # ==> Devise OTP Extension
14
14
  # Configure OTP extension for devise
15
15
 
16
- # How long should the user have to enter their token. To change the default, uncomment and change the below:
17
- #config.otp_authentication_timeout = 3.minutes
16
+ # OTP is mandatory, users are going to be asked to
17
+ # enroll OTP the next time they sign in, before they can successfully complete the session establishment.
18
+ # This is the global value, can also be set on each user.
19
+ #config.otp_mandatory = false
20
+
21
+ # Drift: a window which provides allowance for drift between a user's token device clock
22
+ # (and therefore their OTP tokens) and the authentication server's clock.
23
+ # Expressed in minutes centered at the current time. (Note: it's a number, *NOT* 3.minutes )
24
+ #config.otp_drift_window = 3
25
+
26
+ # Users that have logged in longer than this time ago, are going to be asked their password
27
+ # (and an OTP challenge, if enabled) before they can see or change their otp informations.
28
+ #config.otp_credentials_refresh = 15.minutes
29
+
30
+ # Users are given a list of one-time recovery tokens, for emergency access
31
+ # set to false to disable giving recovery tokens.
32
+ #config.recovery_tokens = 10
33
+
34
+ # The user is allowed to set his browser as "trusted", no more OTP challenges will be
35
+ # asked for that browser, for a limited time.
36
+ # set to false to disable setting the browser as trusted
37
+ #config.otp_trust_persistence = 1.month
38
+
39
+ # The name of this application, to be added to the provisioning
40
+ # url as '<user_email>/application_name' (defaults to the Rails application class)
41
+ #config.otp_uri_application = 'my_application'
18
42
 
19
- # Change time drift settings for valid token values. To change the default, uncomment and change the below:
20
- #config.otp_authentication_time_drift = 3
21
43
  CONTENT
22
44
 
23
45
  inject_into_file "config/initializers/devise.rb", content, :before => /end[ |\n|]+\Z/
@@ -13,7 +13,7 @@ class SignInTest < ActionDispatch::IntegrationTest
13
13
  visit new_user_session_path
14
14
  fill_in 'user_email', :with => 'user@email.invalid'
15
15
  fill_in 'user_password', :with => '12345678'
16
- click_button 'Sign in'
16
+ page.has_content?('Log in') ? click_button('Log in') : click_button('Sign in')
17
17
 
18
18
  assert_equal root_path, current_path
19
19
  end
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+ require 'integration_tests_helper'
3
+
4
+ class TokenTest < ActionDispatch::IntegrationTest
5
+
6
+
7
+ def teardown
8
+ Capybara.reset_sessions!
9
+ end
10
+
11
+ test 'disabling OTP after successfully enabling' do
12
+
13
+ # log in 1fa
14
+ user = enable_otp_and_sign_in
15
+ assert_equal user_otp_credential_path, current_path
16
+
17
+ # otp 2fa
18
+ fill_in 'user_token', :with => ROTP::TOTP.new(user.otp_auth_secret).at(Time.now)
19
+ click_button 'Submit Token'
20
+ assert_equal root_path, current_path
21
+
22
+ # disable OTP
23
+ disable_otp
24
+
25
+ # logout
26
+ sign_out
27
+
28
+ # log back in 1fa
29
+ sign_user_in(user)
30
+
31
+ assert_equal root_path, current_path
32
+
33
+ end
34
+ end
@@ -36,13 +36,26 @@ class ActionDispatch::IntegrationTest
36
36
  user
37
37
  end
38
38
 
39
+ def disable_otp
40
+ visit user_otp_token_path
41
+ uncheck 'user_otp_enabled'
42
+ click_button 'Continue...'
43
+ end
44
+
45
+ def sign_out
46
+ Capybara.reset_sessions!
47
+ end
48
+
39
49
  def sign_user_in(user = nil)
40
50
  user ||= create_full_user
41
51
  resource_name = user.class.name.underscore
42
52
  visit send("new_#{resource_name}_session_path")
43
53
  fill_in "#{resource_name}_email", :with => user.email
44
54
  fill_in "#{resource_name}_password", :with => user.password
45
- click_button 'Sign in'
55
+
56
+ page.has_content?('Log in') ? click_button('Log in') : click_button('Sign in')
46
57
  user
47
58
  end
59
+
60
+
48
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise-otp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
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-12 00:00:00.000000000 Z
11
+ date: 2014-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -96,6 +96,7 @@ files:
96
96
  - app/views/devise_otp/credentials/refresh.html.erb
97
97
  - app/views/devise_otp/credentials/show.html.erb
98
98
  - app/views/devise_otp/tokens/_token_secret.html.erb
99
+ - app/views/devise_otp/tokens/_trusted_devices.html.erb
99
100
  - app/views/devise_otp/tokens/recovery.html.erb
100
101
  - app/views/devise_otp/tokens/show.html.erb
101
102
  - config/locales/en.yml
@@ -161,6 +162,7 @@ files:
161
162
  - test/dummy/script/rails
162
163
  - test/integration/refresh_test.rb
163
164
  - test/integration/sign_in_test.rb
165
+ - test/integration/token_test.rb
164
166
  - test/integration_tests_helper.rb
165
167
  - test/model_tests_helper.rb
166
168
  - test/models/otp_authenticatable_test.rb
@@ -236,6 +238,7 @@ test_files:
236
238
  - test/dummy/script/rails
237
239
  - test/integration/refresh_test.rb
238
240
  - test/integration/sign_in_test.rb
241
+ - test/integration/token_test.rb
239
242
  - test/integration_tests_helper.rb
240
243
  - test/model_tests_helper.rb
241
244
  - test/models/otp_authenticatable_test.rb