devise-two-factor 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise-two-factor might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 080b8e13aabdb40b4f6252a9c80142d40b3f0a31
4
- data.tar.gz: 3f6b9c9d1728b058717a3d18ce4c5735755ee3e3
3
+ metadata.gz: 8b48e2ba9c00be8daeb003205e6e0eb391541a0d
4
+ data.tar.gz: fddf7caf9e1ac9bcf03c4f9b9a41e481001ab13b
5
5
  SHA512:
6
- metadata.gz: 340098e34254cf9627b81ac3baf2618b459c4913708116d3afa9b4a02d1e9f35b92f27ab917e484ca6b255e993efde7fc4b54384a30b26761a11bee08c18b581
7
- data.tar.gz: 1aef5ac6efd39452849e866f391b2e1f0e8307c7ee925ddcdeb2b152659bea30c052231b730a410e8829f37b0352cfabe6c49fefac476640f5fb10dc3164b5e9
6
+ metadata.gz: 2066c0f7459ad2b244d1fba4cfa0f6fbd3d7f6c421eee04a716b3a9c874afa7c986230b1adf919fd67f9e19476f68616d2a5048ce393b359ca5261c5905388ce
7
+ data.tar.gz: 69801b25f82ee866d7e843a326640aab0e566f37a1b54603be2df11b02caf0040ee81b2ab5c7256f7c0fca23eeb493f123e0c98ca05095aa0dc15c65701d7b38
Binary file
data.tar.gz.sig CHANGED
Binary file
data/.gitignore CHANGED
@@ -1,49 +1,47 @@
1
- Gemfile.lock
2
1
  *.gem
3
-
4
- # rcov generated
5
- coverage
6
- coverage.data
7
-
8
- # yard generated
9
- doc
10
- .yardoc
11
-
12
- # bundler
13
- .bundle
14
-
15
- # jeweler generated
16
- pkg
17
-
18
- # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+ *.bridgesupport
18
+ build-iPhoneOS/
19
+ build-iPhoneSimulator/
20
+
21
+ ## Specific to RubyMotion (use of CocoaPods):
19
22
  #
20
- # * Create a file at ~/.gitignore
21
- # * Include files you want ignored
22
- # * Run: git config --global core.excludesfile ~/.gitignore
23
+ # We recommend against adding the Pods directory to your .gitignore. However
24
+ # you should judge for yourself, the pros and cons are mentioned at:
25
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
23
26
  #
24
- # After doing this, these files will be ignored in all your git projects,
25
- # saving you from having to 'pollute' every project you touch with them
26
- #
27
- # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
28
- #
29
- # For MacOS:
30
- #
31
- #.DS_Store
27
+ # vendor/Pods/
32
28
 
33
- # For TextMate
34
- #*.tmproj
35
- #tmtags
29
+ ## Documentation cache and generated files:
30
+ /.yardoc/
31
+ /_yardoc/
32
+ /doc/
33
+ /rdoc/
36
34
 
37
- # For emacs:
38
- #*~
39
- #\#*
40
- #.\#*
35
+ ## Environment normalization:
36
+ /.bundle/
37
+ /vendor/bundle
38
+ /lib/bundler/man/
41
39
 
42
- # For vim:
43
- #*.swp
44
-
45
- # For redcar:
46
- #.redcar
40
+ # for a library or gem, you might want to ignore these files since the code is
41
+ # intended to run in multiple environments; otherwise, check them in:
42
+ Gemfile.lock
43
+ .ruby-version
44
+ .ruby-gemset
47
45
 
48
- # For rubinius:
49
- #*.rbc
46
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
47
+ .rvmrc
@@ -1,5 +1,9 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  cache: bundler
4
+ before_install:
5
+ - gem update --system
6
+ - gem update bundler
3
7
  rvm:
4
8
  - "1.9.3"
5
9
  - "2.0.0"
data/README.md CHANGED
@@ -3,7 +3,7 @@ By [Tinfoil Security](http://tinfoilsecurity.com/)
3
3
 
4
4
  [![Build Status](https://travis-ci.org/tinfoil/devise-two-factor.svg?branch=master)](https://travis-ci.org/tinfoil/devise-two-factor)
5
5
 
6
- Devise-two-factor is a minimalist extension to Devise which offers support for two-factor authentication, through the [TOTP](https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm) scheme. It:
6
+ Devise-Two-Factor is a minimalist extension to Devise which offers support for two-factor authentication, through the [TOTP](https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm) scheme. It:
7
7
 
8
8
  * Allows you to incorporate two-factor authentication into your existing models
9
9
  * Is opinionated about security, so you don't have to be
@@ -11,18 +11,24 @@ Devise-two-factor is a minimalist extension to Devise which offers support for t
11
11
  * Is extensible, and includes two-factor backup codes as an example of how plugins can be structured
12
12
 
13
13
  ## Example App
14
- An example Rails 4 application is provided in demo/. It showcases a minimal example of devise-two-factor in action, and can act as a reference for integrating the gem into your own application.
14
+ An example Rails 4 application is provided in the `demo` directory. It showcases a minimal example of Devise-Two-Factor in action, and can act as a reference for integrating the gem into your own application.
15
15
 
16
- For the demo app to work, create an encryption key and store it as an environment variable. One way to do this is to create a file named `local_env.yml` in the application root. Set the value of 'ENCRYPTION_KEY' in the YML file. That value will be loaded into the application environment by `application.rb`.
16
+ For the demo app to work, create an encryption key and store it as an environment variable. One way to do this is to create a file named `local_env.yml` in the application root. Set the value of `ENCRYPTION_KEY` in the YML file. That value will be loaded into the application environment by `application.rb`.
17
17
 
18
18
  ## Getting Started
19
- Devise-two-factor doesn't require much to get started, but there are a few prerequisites before you can start using it in your application.
19
+ Devise-Two-Factor doesn't require much to get started, but there are a few prerequisites before you can start using it in your application.
20
20
 
21
21
  First, you'll need a Rails application setup with Devise. Visit the Devise [homepage](https://github.com/plataformatec/devise) for instructions.
22
22
 
23
- Next, since devise-two-factor encrypts its secrets before storing them in the database, you'll need to generate an encryption key, and store it in an environment variable of your choice. Set the encryption key in the model that uses devise:
23
+ You can add Devise-Two-Factor to your Gemfile with:
24
24
 
25
+ ```ruby
26
+ gem 'devise-two-factor'
25
27
  ```
28
+
29
+ Next, since Devise-Two-Factor encrypts its secrets before storing them in the database, you'll need to generate an encryption key, and store it in an environment variable of your choice. Set the encryption key in the model that uses Devise:
30
+
31
+ ```ruby
26
32
  devise :two_factor_authenticatable,
27
33
  :otp_secret_encryption_key => ENV['YOUR_ENCRYPTION_KEY_HERE']
28
34
 
@@ -34,20 +40,21 @@ Finally, you can automate all of the required setup by simply running:
34
40
  rails generate devise_two_factor MODEL ENVIRONMENT_VARIABLE
35
41
  ```
36
42
 
37
- Where MODEL is the name of the model you wish to add two-factor functionality to, and ENVIRONMENT_VARIABLE is the name of the variable you're storing your encryption key in.
43
+ Where `MODEL` is the name of the model you wish to add two-factor functionality to (for example `user`), and `ENVIRONMENT_VARIABLE` is the name of the variable you're storing your encryption key in.
38
44
 
39
45
  This generator will add a few columns to the specified model:
40
46
 
41
47
  * encrypted_otp_secret
42
48
  * encrypted_otp_secret_iv
43
49
  * encrypted_otp_secret_salt
50
+ * consumed_timestep
44
51
  * otp_required_for_login
45
52
 
46
- It also adds the :two_factor_authenticatable directive to your model, and sets up your encryption key. If present, it will remove :database_authenticatable from the model, as the two strategies are incompatible. Lastly, the generator will add a Warden config block to your Devise initializer, which enables the strategies required for two-factor authenticatation.
53
+ It also adds the :two_factor_authenticatable directive to your model, and sets up your encryption key. If present, it will remove :database_authenticatable from the model, as the two strategies are incompatible. Lastly, the generator will add a Warden config block to your Devise initializer, which enables the strategies required for two-factor authentication.
47
54
 
48
55
  If you're running Rails 3, or do not have strong parameters enabled, the generator will also setup the required mass-assignment security options in your model.
49
56
 
50
- If you're running Rails 4, you'll also need to whitelist `:otp_attempt` as a permitted parameter in Devise `:sign_in` controller. You can do this by adding the following to your `application_controller.rb`
57
+ If you're running Rails 4, you'll also need to whitelist `:otp_attempt` as a permitted parameter in Devise `:sign_in` controller. You can do this by adding the following to your `application_controller.rb`:
51
58
 
52
59
  ```ruby
53
60
  before_action :configure_permitted_parameters, if: :devise_controller?
@@ -61,10 +68,10 @@ def configure_permitted_parameters
61
68
  end
62
69
  ```
63
70
 
64
- **After running the generator, verify that :database_authenticatable is not being loaded by your model. The generator will try to remove it, but if you have a non-standard Devise setup, this step may fail. Loading both :database_authenticatable and :two_factor_authenticatable in a model will allow users to bypass two-factor authenticatable due to the way Warden handles cascading strategies.**
71
+ **After running the generator, verify that :database_authenticatable is not being loaded by your model. The generator will try to remove it, but if you have a non-standard Devise setup, this step may fail. Loading both :database_authenticatable and `:two_factor_authenticatable` in a model will allow users to bypass two-factor authenticatable due to the way Warden handles cascading strategies.**
65
72
 
66
73
  ## Designing Your Workflow
67
- Devise-two-factor only worries about the backend, leaving the details of the integration up to you. This means that you're responsible for building the UI that drives the gem. While there is an example Rails application included in the gem, it is important to remember that this gem is intentionally very open-ended, and you should build a user experience which fits your individual application.
74
+ Devise-Two-Factor only worries about the backend, leaving the details of the integration up to you. This means that you're responsible for building the UI that drives the gem. While there is an example Rails application included in the gem, it is important to remember that this gem is intentionally very open-ended, and you should build a user experience which fits your individual application.
68
75
 
69
76
  There are two key workflows you'll have to think about:
70
77
 
@@ -75,7 +82,7 @@ We chose to keep things as simple as possible, and our implementation can be fou
75
82
 
76
83
 
77
84
  ### Logging In
78
- Logging in with two-factor authentication works extremely similarly to regular database authentication in Devise. The TwoFactorAuthenticatable strategy accepts three parameters:
85
+ Logging in with two-factor authentication works extremely similarly to regular database authentication in Devise. The `TwoFactorAuthenticatable` strategy accepts three parameters:
79
86
 
80
87
  1. email
81
88
  2. password
@@ -84,9 +91,9 @@ Logging in with two-factor authentication works extremely similarly to regular d
84
91
  These parameters can be submitted to the standard Devise login route, and the strategy will handle the authentication of the user for you.
85
92
 
86
93
  ### Disabling Automatic Login After Password Resets
87
- If you use the Devise ```recoverable``` strategy, the default behavior after a password reset is to automatically authenticate the user and log them in. This is obviously a problem if a user has two-factor authentication enabled, as resetting the password would get around the 2FA requirement.
94
+ If you use the Devise ```recoverable``` strategy, the default behavior after a password reset is to automatically authenticate the user and log them in. This is obviously a problem if a user has two-factor authentication enabled, as resetting the password would get around the two-factor requirement.
88
95
 
89
- Because of this, you need to set `sign_in_after_reset_password` to false (either globally in your Devise initializer or via `devise_for`)
96
+ Because of this, you need to set `sign_in_after_reset_password` to `false` (either globally in your Devise initializer or via `devise_for`).
90
97
 
91
98
  ### Enabling Two-Factor Authentication
92
99
  Enabling two-factor authentication for a user is easy. For example, if my user model were named User, I could do the following:
@@ -107,26 +114,33 @@ If you instead to decide to send the one-time password to the user directly, suc
107
114
  current_user.current_otp
108
115
  ```
109
116
 
110
- The generated code will be valid for the duration specified by otp_allowed_drift.
117
+ The generated code will be valid for the duration specified by `otp_allowed_drift`.
111
118
 
112
119
  However you decide to handle enrollment, there are a few important considerations to be made:
113
120
 
114
- * Whether you'll force the use of two-factor authentication, and if so, how you'll migrate existing users to system, and what your onboarding experience will look like
121
+ * Whether you'll force the use of two-factor authentication, and if so, how you'll migrate existing users to system, and what your on-boarding experience will look like
115
122
  * If you authenticate using SMS, you'll want to verify the user's ownership of the phone, in much the same way you're probably verifying their email address
116
- * How you'll handle device revocation in the event that a user loses access to their device, or that device is rendered temporarily unavailable (This gem includes TwoFactorBackupable as an example extension meant to solve this problem)
123
+ * How you'll handle device revocation in the event that a user loses access to their device, or that device is rendered temporarily unavailable (This gem includes `TwoFactorBackupable` as an example extension meant to solve this problem)
117
124
 
118
125
  It sounds like a lot of work, but most of these problems have been very elegantly solved by other people. We recommend taking a look at the excellent workflows used by Heroku and Google for inspiration.
119
126
 
127
+ ### Filtering sensitive parameters from the logs
128
+ To prevent two-factor authentication codes from leaking if your application logs get breached, you'll want to filter sensitive parameters from the Rails logs. Add the following to `config/initializers/filter_parameter_logging.rb`:
129
+
130
+ ```ruby
131
+ Rails.application.config.filter_parameters += [:otp_attempt]
132
+ ```
133
+
120
134
  ## Backup Codes
121
- Devise-two-factor is designed with extensibility in mind. One such extension, TwoFactorBackupable, is included and serves as a good example of how to extend this gem. This plugin allows you to add the ability to generate single-use backup codes for a user, which they may use to bypass two-factor authentication, in the event that they lose access to their device.
135
+ Devise-Two-Factor is designed with extensibility in mind. One such extension, `TwoFactorBackupable`, is included and serves as a good example of how to extend this gem. This plugin allows you to add the ability to generate single-use backup codes for a user, which they may use to bypass two-factor authentication, in the event that they lose access to their device.
122
136
 
123
- To install it, you need to add the :two_factor_backupable directive to your model.
137
+ To install it, you need to add the `:two_factor_backupable` directive to your model.
124
138
 
125
139
  ```ruby
126
140
  devise :two_factor_backupable
127
141
  ```
128
142
 
129
- You'll also be required to enable the :two_factor_backupable strategy, by adding the following line to your Warden config in your Devise initializer, substituting :user for the name of your Devise scope.
143
+ You'll also be required to enable the `:two_factor_backupable` strategy, by adding the following line to your Warden config in your Devise initializer, substituting :user for the name of your Devise scope.
130
144
 
131
145
  ```ruby
132
146
  manager.default_strategies(:scope => :user).unshift :two_factor_backupable
@@ -137,6 +151,7 @@ The final installation step is dependent on your version of Rails. If you're not
137
151
  ```ruby
138
152
  class AddDeviseTwoFactorBackupableToUsers < ActiveRecord::Migration
139
153
  def change
154
+ # Change type from :string to :text if using MySQL database
140
155
  add_column :users, :otp_backup_codes, :string, array: true
141
156
  end
142
157
  end
@@ -160,13 +175,14 @@ devise :two_factor_backupable, otp_backup_code_length: 32,
160
175
  ```
161
176
 
162
177
  ### Help! I'm not using Rails 4.0!
163
- Don't worry! TwoFactorBackupable stores the backup codes as an array of strings in the database. In Rails 4.0 this is supported natively, but in earlier versions you can use a gem to emulate this behaviour: we recommend [activerecord-postgres-array](https://github.com/tlconnor/activerecord-postgres-array).
178
+ Don't worry! `TwoFactorBackupable` stores the backup codes as an array of strings in the database. In Rails 4.0 this is supported natively, but in earlier versions you can use a gem to emulate this behavior: we recommend [activerecord-postgres-array](https://github.com/tlconnor/activerecord-postgres-array).
164
179
 
165
180
  You'll then simply have to create a migration to add an array named `otp_backup_codes` to your model. If you use the above gem, this migration might look like:
166
181
 
167
182
  ```ruby
168
183
  class AddTwoFactorBackupCodesToUsers < ActiveRecord::Migration
169
184
  def change
185
+ # Change type from :string_array to :text_array if using MySQL database
170
186
  add_column :users, :otp_backup_codes, :string_array
171
187
  end
172
188
  end
@@ -175,7 +191,7 @@ end
175
191
  Now just continue with the setup in the previous section, skipping the generator step.
176
192
 
177
193
  ## Testing
178
- Devise-two-factor includes shared-examples for both TwoFactorAuthenticatable and TwoFactorBackupable. Adding the following two lines to the specs for your two-factor enabled models will allow you to test your models for two-factor functionality:
194
+ Devise-Two-Factor includes shared-examples for both `TwoFactorAuthenticatable` and `TwoFactorBackupable`. Adding the following two lines to the specs for your two-factor enabled models will allow you to test your models for two-factor functionality:
179
195
 
180
196
  ```ruby
181
197
  require 'devise_two_factor/spec_helpers'
@@ -26,9 +26,9 @@ Gem::Specification.new do |s|
26
26
 
27
27
  s.add_runtime_dependency 'railties'
28
28
  s.add_runtime_dependency 'activesupport'
29
- s.add_runtime_dependency 'attr_encrypted', '~> 1.3.2'
30
- s.add_runtime_dependency 'devise', '~> 3.5.0'
31
- s.add_runtime_dependency 'rotp', '~> 2'
29
+ s.add_runtime_dependency 'attr_encrypted', '~> 1.3'
30
+ s.add_runtime_dependency 'devise', '~> 3.5'
31
+ s.add_runtime_dependency 'rotp', '~> 2.0'
32
32
 
33
33
  s.add_development_dependency 'activemodel'
34
34
  s.add_development_dependency 'bundler', '> 1.0'
@@ -22,7 +22,7 @@ module Devise
22
22
  # If this hasn't been generated yet, pass a secret as an option
23
23
  def validate_and_consume_otp!(code, options = {})
24
24
  otp_secret = options[:otp_secret] || self.otp_secret
25
- return false unless otp_secret.present?
25
+ return false unless code.present? && otp_secret.present?
26
26
 
27
27
  totp = self.otp(otp_secret)
28
28
  return consume_otp! if totp.verify_with_drift(code, self.class.otp_allowed_drift)
@@ -71,6 +71,11 @@ shared_examples 'two_factor_authenticatable' do
71
71
  expect(subject.validate_and_consume_otp!(otp)).to be true
72
72
  end
73
73
 
74
+ it 'fails a nil OTP value' do
75
+ otp = nil
76
+ expect(subject.validate_and_consume_otp!(otp)).to be false
77
+ end
78
+
74
79
  it 'validates an OTP within the allowed drift' do
75
80
  otp = ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift, true)
76
81
  expect(subject.validate_and_consume_otp!(otp)).to be true
@@ -1,3 +1,3 @@
1
1
  module DeviseTwoFactor
2
- VERSION = '2.0.1'.freeze
2
+ VERSION = '2.1.0'.freeze
3
3
  end
@@ -2,9 +2,12 @@ require 'spec_helper'
2
2
  require 'active_model'
3
3
 
4
4
  class TwoFactorAuthenticatableDouble
5
+ extend ::ActiveModel::Callbacks
5
6
  include ::ActiveModel::Validations::Callbacks
6
7
  extend ::Devise::Models
7
8
 
9
+ define_model_callbacks :update
10
+
8
11
  devise :two_factor_authenticatable, :otp_secret_encryption_key => 'test-key'
9
12
 
10
13
  attr_accessor :consumed_timestep
@@ -1,9 +1,13 @@
1
1
  require 'spec_helper'
2
+ require 'active_model'
2
3
 
3
4
  class TwoFactorBackupableDouble
5
+ extend ::ActiveModel::Callbacks
4
6
  include ::ActiveModel::Validations::Callbacks
5
7
  extend ::Devise::Models
6
8
 
9
+ define_model_callbacks :update
10
+
7
11
  devise :two_factor_authenticatable, :two_factor_backupable,
8
12
  :otp_secret_encryption_key => 'test-key'
9
13
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise-two-factor
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Wilton
@@ -84,160 +84,160 @@ cert_chain:
84
84
  5C31v4YyRBnNCp0pN66nxYX2avEiQ8riTBP5mlkPPOhsIoYQHHe2Uj75aVpu0LZ3
85
85
  cdFzuO4GC1dV0Wv+dsDm+MyF7DT5E9pUPXpnMJuPvPrFpCb+wrFlszW9hGjXbQ==
86
86
  -----END CERTIFICATE-----
87
- date: 2015-10-01 00:00:00.000000000 Z
87
+ date: 2016-03-23 00:00:00.000000000 Z
88
88
  dependencies:
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: railties
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - '>='
93
+ - - ">="
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
- - - '>='
100
+ - - ">="
101
101
  - !ruby/object:Gem::Version
102
102
  version: '0'
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: activesupport
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - '>='
107
+ - - ">="
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
- - - '>='
114
+ - - ">="
115
115
  - !ruby/object:Gem::Version
116
116
  version: '0'
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: attr_encrypted
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
- - - ~>
121
+ - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: 1.3.2
123
+ version: '1.3'
124
124
  type: :runtime
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - ~>
128
+ - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: 1.3.2
130
+ version: '1.3'
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: devise
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
- - - ~>
135
+ - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: 3.5.0
137
+ version: '3.5'
138
138
  type: :runtime
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
- - - ~>
142
+ - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: 3.5.0
144
+ version: '3.5'
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: rotp
147
147
  requirement: !ruby/object:Gem::Requirement
148
148
  requirements:
149
- - - ~>
149
+ - - "~>"
150
150
  - !ruby/object:Gem::Version
151
- version: '2'
151
+ version: '2.0'
152
152
  type: :runtime
153
153
  prerelease: false
154
154
  version_requirements: !ruby/object:Gem::Requirement
155
155
  requirements:
156
- - - ~>
156
+ - - "~>"
157
157
  - !ruby/object:Gem::Version
158
- version: '2'
158
+ version: '2.0'
159
159
  - !ruby/object:Gem::Dependency
160
160
  name: activemodel
161
161
  requirement: !ruby/object:Gem::Requirement
162
162
  requirements:
163
- - - '>='
163
+ - - ">="
164
164
  - !ruby/object:Gem::Version
165
165
  version: '0'
166
166
  type: :development
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  requirements:
170
- - - '>='
170
+ - - ">="
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0'
173
173
  - !ruby/object:Gem::Dependency
174
174
  name: bundler
175
175
  requirement: !ruby/object:Gem::Requirement
176
176
  requirements:
177
- - - '>'
177
+ - - ">"
178
178
  - !ruby/object:Gem::Version
179
179
  version: '1.0'
180
180
  type: :development
181
181
  prerelease: false
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
- - - '>'
184
+ - - ">"
185
185
  - !ruby/object:Gem::Version
186
186
  version: '1.0'
187
187
  - !ruby/object:Gem::Dependency
188
188
  name: rspec
189
189
  requirement: !ruby/object:Gem::Requirement
190
190
  requirements:
191
- - - '>'
191
+ - - ">"
192
192
  - !ruby/object:Gem::Version
193
193
  version: '3'
194
194
  type: :development
195
195
  prerelease: false
196
196
  version_requirements: !ruby/object:Gem::Requirement
197
197
  requirements:
198
- - - '>'
198
+ - - ">"
199
199
  - !ruby/object:Gem::Version
200
200
  version: '3'
201
201
  - !ruby/object:Gem::Dependency
202
202
  name: simplecov
203
203
  requirement: !ruby/object:Gem::Requirement
204
204
  requirements:
205
- - - '>='
205
+ - - ">="
206
206
  - !ruby/object:Gem::Version
207
207
  version: '0'
208
208
  type: :development
209
209
  prerelease: false
210
210
  version_requirements: !ruby/object:Gem::Requirement
211
211
  requirements:
212
- - - '>='
212
+ - - ">="
213
213
  - !ruby/object:Gem::Version
214
214
  version: '0'
215
215
  - !ruby/object:Gem::Dependency
216
216
  name: faker
217
217
  requirement: !ruby/object:Gem::Requirement
218
218
  requirements:
219
- - - '>='
219
+ - - ">="
220
220
  - !ruby/object:Gem::Version
221
221
  version: '0'
222
222
  type: :development
223
223
  prerelease: false
224
224
  version_requirements: !ruby/object:Gem::Requirement
225
225
  requirements:
226
- - - '>='
226
+ - - ">="
227
227
  - !ruby/object:Gem::Version
228
228
  version: '0'
229
229
  - !ruby/object:Gem::Dependency
230
230
  name: timecop
231
231
  requirement: !ruby/object:Gem::Requirement
232
232
  requirements:
233
- - - '>='
233
+ - - ">="
234
234
  - !ruby/object:Gem::Version
235
235
  version: '0'
236
236
  type: :development
237
237
  prerelease: false
238
238
  version_requirements: !ruby/object:Gem::Requirement
239
239
  requirements:
240
- - - '>='
240
+ - - ">="
241
241
  - !ruby/object:Gem::Version
242
242
  version: '0'
243
243
  description: Barebones two-factor authentication with Devise
@@ -246,9 +246,9 @@ executables: []
246
246
  extensions: []
247
247
  extra_rdoc_files: []
248
248
  files:
249
- - .gitignore
250
- - .rspec
251
- - .travis.yml
249
+ - ".gitignore"
250
+ - ".rspec"
251
+ - ".travis.yml"
252
252
  - CONTRIBUTING.md
253
253
  - Gemfile
254
254
  - LICENSE
@@ -283,17 +283,17 @@ require_paths:
283
283
  - lib
284
284
  required_ruby_version: !ruby/object:Gem::Requirement
285
285
  requirements:
286
- - - '>='
286
+ - - ">="
287
287
  - !ruby/object:Gem::Version
288
288
  version: '0'
289
289
  required_rubygems_version: !ruby/object:Gem::Requirement
290
290
  requirements:
291
- - - '>='
291
+ - - ">="
292
292
  - !ruby/object:Gem::Version
293
293
  version: '0'
294
294
  requirements: []
295
295
  rubyforge_project: devise-two-factor
296
- rubygems_version: 2.4.7
296
+ rubygems_version: 2.4.5.1
297
297
  signing_key:
298
298
  specification_version: 4
299
299
  summary: Barebones two-factor authentication with Devise
@@ -301,4 +301,3 @@ test_files:
301
301
  - spec/devise/models/two_factor_authenticatable_spec.rb
302
302
  - spec/devise/models/two_factor_backupable_spec.rb
303
303
  - spec/spec_helper.rb
304
- has_rdoc:
metadata.gz.sig CHANGED
Binary file