devise-two-factor 3.0.2 → 4.0.1

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
- SHA1:
3
- metadata.gz: 6153cf66eccb7295eb920bc6235d8de03d6b573a
4
- data.tar.gz: f5c0f448a63162bc4ed51ec8ef7cdd59de4359ff
2
+ SHA256:
3
+ metadata.gz: deebbcf66a27a576c35731a7079f7aa31dead706b97ef36d8a492e9842da2d99
4
+ data.tar.gz: 9659a191445fd665979f42c8a81be6282906dd90f5ebdd1ad714ba106e746a01
5
5
  SHA512:
6
- metadata.gz: acc1ea71e99991545f65d7a94521619b6dc1bed4dd0f38a1c2664741905505b673e5af84e6a4f1376c57fdd59809a3d50826829b9c71f632a79688879f5d55c9
7
- data.tar.gz: b4be516c6465446c97b03f686f7fbb51764dff6dff72fabdb5d5b24e8ea2c4b3159967b3a8bc15d1067d05e2e0261a603981f6ee77aa7818b6907699774337e0
6
+ metadata.gz: ea90eaac55d11f619fb76709a576d8df42d413f7eaf4ceedfa72767531fe2d740a819192846cb12070fe32ab0dcb3e92b3a971bef17f86304d76f10eb2d8ba9a
7
+ data.tar.gz: 55aba2b1a2bae479246b8d579ca4397db1e983857cc75565a1232dfed7a4eb4e5c57363e982ea5d9a433de5e0ab2ad17aee51a5ee79387df1bc7bb15e17a71ba
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,47 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ pull_request:
7
+
8
+ jobs:
9
+ tests:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ # Due to https://github.com/actions/runner/issues/849, we should quote versions
15
+ ruby: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', 'truffleruby-head']
16
+ rails: ['4.1', '4.2', '5.0', '5.1', '5.2', '6.0', '6.1']
17
+ exclude:
18
+ - {ruby: '2.3', rails: '6.0'}
19
+ - {ruby: '2.3', rails: '6.1'}
20
+ - {ruby: '2.4', rails: '6.0'}
21
+ - {ruby: '2.4', rails: '6.1'}
22
+ - {ruby: '2.7', rails: '4.1'}
23
+ - {ruby: '2.7', rails: '4.2'}
24
+ - {ruby: '3.0', rails: '4.1'}
25
+ - {ruby: '3.0', rails: '4.2'}
26
+ - {ruby: 'truffleruby-head', rails: '4.1'}
27
+ - {ruby: 'truffleruby-head', rails: '4.2'}
28
+
29
+ name: Ruby ${{ matrix.ruby }}, Rails ${{ matrix.rails }}
30
+ env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
31
+ BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_${{ matrix.rails }}.gemfile
32
+ steps:
33
+ - uses: actions/checkout@v2
34
+ - name: Set up Ruby
35
+ uses: ruby/setup-ruby@v1
36
+ with:
37
+ ruby-version: ${{ matrix.ruby }}
38
+ bundler-cache: true
39
+ - name: Print versions
40
+ continue-on-error: true
41
+ run: |
42
+ ruby --version
43
+ bundle --version
44
+ echo "RubyGems version `gem --version`"
45
+ bundle exec rails --version
46
+ - name: Run tests
47
+ run: bundle exec rake
data/Appraisals CHANGED
@@ -1,19 +1,34 @@
1
- appraise "rails-4-1" do
1
+ appraise "rails-4.1" do
2
2
  gem 'railties', '~> 4.1'
3
3
  gem 'activesupport', '~> 4.1'
4
4
  end
5
5
 
6
- appraise "rails-4-2" do
6
+ appraise "rails-4.2" do
7
7
  gem 'railties', '~> 4.2'
8
8
  gem 'activesupport', '~> 4.2'
9
9
  end
10
10
 
11
- appraise "rails-5-0" do
11
+ appraise "rails-5.0" do
12
12
  gem 'railties', '~> 5.0'
13
13
  gem 'activesupport', '~> 5.0'
14
14
  end
15
15
 
16
- appraise "rails-5-1" do
16
+ appraise "rails-5.1" do
17
17
  gem 'railties', '~> 5.1'
18
18
  gem 'activesupport', '~> 5.1'
19
19
  end
20
+
21
+ appraise "rails-5.2" do
22
+ gem 'railties', '~> 5.2'
23
+ gem 'activesupport', '~> 5.2'
24
+ end
25
+
26
+ appraise "rails-6.0" do
27
+ gem 'railties', '~> 6.0'
28
+ gem 'activesupport', '~> 6.0'
29
+ end
30
+
31
+ appraise "rails-6.1" do
32
+ gem 'railties', '~> 6.1'
33
+ gem 'activesupport', '~> 6.1'
34
+ end
data/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 4.0.1
6
+ - Convert CI from Travis CI to Github Actions ([#198](https://github.com/tinfoil/devise-two-factor/pull/198))
7
+ - Fix ActiveSupport::Testing::TimeHelpers require in shared examples ([#191](https://github.com/tinfoil/devise-two-factor/pull/191))
8
+ - Accept whitespace in provided codes ([#195](https://github.com/tinfoil/devise-two-factor/pull/195))
9
+ - Add Truffleruby head to CI ([#200](https://github.com/tinfoil/devise-two-factor/pull/200))
10
+
11
+ ## 4.0.0
12
+ - [breaking] Drop support for Ruby <= 2.2
13
+ - Update ROTP
14
+ - Add Rails 6.1 support
15
+ - Remove timecop dependency
16
+ - Clarify changes in project ownership
17
+ - Bugfixes & cleanup
18
+
19
+ ## 3.1.0
20
+ - Add Rails 6.0 support
21
+ - New gem signing certificate
22
+ - Fix paranoid-mode being ignored
23
+
24
+ ## 3.0.3
25
+ - Add Rails 5.2 support
26
+
5
27
  ## 3.0.2
6
28
  - Add Rails 5.1 support
7
29
 
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Tinfoil Security, Inc.
3
+ Copyright (c) 2014 Synopsys, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,15 +1,18 @@
1
1
  # Devise-Two-Factor Authentication
2
- By [Tinfoil Security](http://tinfoilsecurity.com/)
2
+ By [Tinfoil Security](https://www.tinfoilsecurity.com/) (acq. [Synopsys](https://www.synopsys.com/) 2020). Interested in [working with us](https://www.synopsys.com/careers.html)? We're hiring!
3
3
 
4
- [![Build Status](https://travis-ci.org/tinfoil/devise-two-factor.svg?branch=master)](https://travis-ci.org/tinfoil/devise-two-factor)
4
+ ![Build Status](https://github.com/tinfoil/devise-two-factor/actions/workflows/ci.yml/badge.svg)
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) 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
10
10
  * Integrates easily with two-factor applications like [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en) and [Authy](https://authy.com/)
11
11
  * Is extensible, and includes two-factor backup codes as an example of how plugins can be structured
12
12
 
13
+ ## Contributing
14
+ We welcome pull requests, bug reports, and other contributions. We're especially looking for help getting this gem fully compatible with Rails 5+ and squashing any deprecation messages.
15
+
13
16
  ## Example App
14
17
  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
18
 
@@ -50,7 +53,13 @@ This generator will add a few columns to the specified model:
50
53
  * consumed_timestep
51
54
  * otp_required_for_login
52
55
 
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.
56
+ Remember to apply the new migration.
57
+
58
+ ```ruby
59
+ bundle exec rake db:migrate
60
+ ```
61
+
62
+ 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.
54
63
 
55
64
  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.
56
65
 
@@ -82,7 +91,7 @@ def configure_permitted_parameters
82
91
  end
83
92
  ```
84
93
 
85
- **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.**
94
+ **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.**
86
95
 
87
96
  ## Designing Your Workflow
88
97
  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.
@@ -92,7 +101,7 @@ There are two key workflows you'll have to think about:
92
101
  1. Logging in with two-factor authentication
93
102
  2. Enabling two-factor authentication for a given user
94
103
 
95
- We chose to keep things as simple as possible, and our implementation can be found by registering at [Tinfoil Security](https://tinfoilsecurity.com/), and enabling two-factor authentication from the [security settings page](https://www.tinfoilsecurity.com/account/security).
104
+ We chose to keep things as simple as possible, and our implementation can be found by registering at [Tinfoil Security](https://www.tinfoilsecurity.com/), and enabling two-factor authentication from the [security settings page](https://www.tinfoilsecurity.com/account/security).
96
105
 
97
106
 
98
107
  ### Logging In
@@ -105,7 +114,7 @@ Logging in with two-factor authentication works extremely similarly to regular d
105
114
  These parameters can be submitted to the standard Devise login route, and the strategy will handle the authentication of the user for you.
106
115
 
107
116
  ### Disabling Automatic Login After Password Resets
108
- 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.
117
+ 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.
109
118
 
110
119
  Because of this, you need to set `sign_in_after_reset_password` to `false` (either globally in your Devise initializer or via `devise_for`).
111
120
 
@@ -139,7 +148,13 @@ If you instead to decide to send the one-time password to the user directly, suc
139
148
  current_user.current_otp
140
149
  ```
141
150
 
142
- The generated code will be valid for the duration specified by `otp_allowed_drift`.
151
+ The generated code will be valid for the duration specified by `otp_allowed_drift`. This value can be modified by adding a config in `config/initializers/devise.rb`.
152
+ ```ruby
153
+ Devise.otp_allowed_drift = 240 # value in seconds
154
+ Devise.setup do |config|
155
+ ...
156
+ end
157
+ ```
143
158
 
144
159
  However you decide to handle enrollment, there are a few important considerations to be made:
145
160
 
@@ -224,3 +239,20 @@ require 'devise_two_factor/spec_helpers'
224
239
  it_behaves_like "two_factor_authenticatable"
225
240
  it_behaves_like "two_factor_backupable"
226
241
  ```
242
+
243
+ ## Troubleshooting
244
+ If you are using Rails 4.x and Ruby >= 2.7, you may get an error like
245
+
246
+ ```
247
+ An error occurred while loading ./spec/devise/models/two_factor_authenticatable_spec.rb.
248
+ Failure/Error: require 'devise'
249
+
250
+ NoMethodError:
251
+ undefined method `new' for BigDecimal:Class
252
+ ```
253
+ see https://github.com/ruby/bigdecimal#which-version-should-you-select and https://github.com/ruby/bigdecimal/issues/127
254
+ for more details, but you should be able to solve this
255
+ by explicitly requiring an older version of bigdecimal in your gemfile like
256
+ ```
257
+ gem "bigdecimal", "~> 1.4"
258
+ ```
@@ -1,35 +1,35 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIIGATCCA+mgAwIBAgIJAK2u0LojMCOOMA0GCSqGSIb3DQEBDQUAMIGcMQswCQYD
3
- VQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0bzEfMB0GA1UE
4
- ChMWVGluZm9pbCBTZWN1cml0eSwgSW5jLjEfMB0GA1UEAxMWVGluZm9pbCBTZWN1
5
- cml0eSwgSW5jLjEqMCgGCSqGSIb3DQEJARYbc3VwcG9ydEB0aW5mb2lsc2VjdXJp
6
- dHkuY29tMB4XDTE3MTAwNTIyMTIwMFoXDTE4MTAwNTIyMTIwMFowgYgxCzAJBgNV
7
- BAYTAlVTMQswCQYDVQQIEwJDQTEfMB0GA1UEChMWVGluZm9pbCBTZWN1cml0eSwg
8
- SW5jLjEdMBsGA1UEAxMUdGluZm9pbHNlY3VyaXR5LWdlbXMxLDAqBgkqhkiG9w0B
9
- CQEWHWVuZ2luZWVyc0B0aW5mb2lsc2VjdXJpdHkuY29tMIICIjANBgkqhkiG9w0B
10
- AQEFAAOCAg8AMIICCgKCAgEAzSWDR/A/vJQAi7dys4xCD7N11QQj2jJtng/15PTj
11
- k7g1fzaoDCtInA/TEcTFLUt0gqwvUHD6HF0++n9i0N8lSbivqwVGrMphBEuOzyMd
12
- nMwuJ+B4GtMTz7gaYqDtuqGkRbKG8s4fUTziG52H6Y8qrXa25vmMjN7D0eF8xYq7
13
- /caJk+BPU+EQi4DkB03Cyi/SvZvhDez3lXVVF1dD2u3FbNryVCnnbHe756+i825/
14
- E6D5P+yf+Fvd9T22niOcoPWbmkWvStiGmNU5DyOuzVuKiorQVXqUZV8Okm+02HFJ
15
- 3FhEP3guQqZzpqlKxubXxg/HHOWhmTpIrVv1V2YFY/NcYAr9YZOB4xK66quBQTQG
16
- gkjcgX8EdE1GKoNZTdZ2zYzisH2+mEZ9OkdqL3BSRtLZhobEFCwq+n1vLtk30jPl
17
- PVhUiCcdoK4rq3mOxGT8IPzILFIllFjBXps9xlWF1iUd3TdqVvVKq965IymWwNG7
18
- LRlmoSTvR7hXQ2pEMaGkz2D7U0AwvpLJJDupShtSiyKGdYi2cwdSrNbxHshO5adY
19
- ploKVKvqttzxZLdYCAYv+LRr87C2cntuUFNmPly85XQjZvg8kRV2fkPmyt9yL3lH
20
- lFhDr+E9ak1xwDsqcs5oKHVURvz65bEjDgXxOdeZBtZgzBo0XAqRLZbJIMVG3+6j
21
- O4UCAwEAAaNYMFYwCQYDVR0TBAIwADBJBgNVHR8EQjBAMD6gPKA6hjhodHRwczov
22
- L3d3dy50aW5mb2lsc2VjdXJpdHkuY29tL3NlY3VyaXR5L3Jldm9jYXRpb25fbGlz
23
- dDANBgkqhkiG9w0BAQ0FAAOCAgEAOWgFA1OGyomztWe+GvGgB1JIwPqzIhhFaSLR
24
- uXlp275fyIrue9ugflj93j346PL1y88ffbzdK5tm25ZJcCX/itacoAPMHcxQeq01
25
- IFG4+xO0C+sfpklgWzYy0wrg9iTctbpk7KKtxMroVsGWK1k8BBc/1Wi3vnYxqeNO
26
- 2z670EtC1xuiOr0xY8SDO+LuBaO6SptvnIs29RVTVxaaYToUO54nX4kxMFwSrkBP
27
- Zhe6rprP8u0tO3q4CzI+MfmXJEFOC8ABF6odZmODVJRb5dQrxsqSwN8kpTdkg0As
28
- w44Qv8VIr60YBpWzpVB90ZFkQAnJXty9LaSvc7uiTExDSFiDwNx7JEgGcjLVTGZS
29
- I1LBc63m+uhZghQzm3Pi3i6hZFm5VdaFuOYL5uNsJf5dJ4Qo+K1WwmZ7y4VpuInn
30
- uWzaz2XrvJTY3/mv3JifXdq8SUFw8RnjUyc6fQo15K1jYbgY7FqfByH0Xx9avcO3
31
- wprlcVYL0flWPzWJdJ4YwY4WZ4LvjPhxOYmE28670DIOQoSajqLS7VUqXA1psgI1
32
- UqyeEsa9DYAUXhKYFarMPfzwa/SGOMX64OkGXNsVCWj93QiwE7tOJQRELouYAHI7
33
- PaA022yxKoh+TitCDcZLQC7ewl554vH1xWicHaLNuuhy6yKmqKiVR8kqtYLrijgo
34
- ztlV910=
2
+ MIIGADCCA+igAwIBAgIIP4wV6YA6CO0wDQYJKoZIhvcNAQENBQAwgZwxCzAJBgNV
3
+ BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJUGFsbyBBbHRvMR8wHQYDVQQK
4
+ ExZUaW5mb2lsIFNlY3VyaXR5LCBJbmMuMR8wHQYDVQQDExZUaW5mb2lsIFNlY3Vy
5
+ aXR5LCBJbmMuMSowKAYJKoZIhvcNAQkBFhtzdXBwb3J0QHRpbmZvaWxzZWN1cml0
6
+ eS5jb20wHhcNMjEwNDA4MTUxODAwWhcNMjExMjI0MDUwNzAwWjCBiDELMAkGA1UE
7
+ BhMCVVMxCzAJBgNVBAgTAkNBMR8wHQYDVQQKExZUaW5mb2lsIFNlY3VyaXR5LCBJ
8
+ bmMuMR0wGwYDVQQDExR0aW5mb2lsc2VjdXJpdHktZ2VtczEsMCoGCSqGSIb3DQEJ
9
+ ARYdZW5naW5lZXJzQHRpbmZvaWxzZWN1cml0eS5jb20wggIiMA0GCSqGSIb3DQEB
10
+ AQUAA4ICDwAwggIKAoICAQDNJYNH8D+8lACLt3KzjEIPs3XVBCPaMm2eD/Xk9OOT
11
+ uDV/NqgMK0icD9MRxMUtS3SCrC9QcPocXT76f2LQ3yVJuK+rBUasymEES47PIx2c
12
+ zC4n4Hga0xPPuBpioO26oaRFsobyzh9RPOIbnYfpjyqtdrbm+YyM3sPR4XzFirv9
13
+ xomT4E9T4RCLgOQHTcLKL9K9m+EN7PeVdVUXV0Pa7cVs2vJUKedsd7vnr6Lzbn8T
14
+ oPk/7J/4W931PbaeI5yg9ZuaRa9K2IaY1TkPI67NW4qKitBVepRlXw6Sb7TYcUnc
15
+ WEQ/eC5CpnOmqUrG5tfGD8cc5aGZOkitW/VXZgVj81xgCv1hk4HjErrqq4FBNAaC
16
+ SNyBfwR0TUYqg1lN1nbNjOKwfb6YRn06R2ovcFJG0tmGhsQULCr6fW8u2TfSM+U9
17
+ WFSIJx2griureY7EZPwg/MgsUiWUWMFemz3GVYXWJR3dN2pW9Uqr3rkjKZbA0bst
18
+ GWahJO9HuFdDakQxoaTPYPtTQDC+kskkO6lKG1KLIoZ1iLZzB1Ks1vEeyE7lp1im
19
+ WgpUq+q23PFkt1gIBi/4tGvzsLZye25QU2Y+XLzldCNm+DyRFXZ+Q+bK33IveUeU
20
+ WEOv4T1qTXHAOypyzmgodVRG/PrlsSMOBfE515kG1mDMGjRcCpEtlskgxUbf7qM7
21
+ hQIDAQABo1gwVjAJBgNVHRMEAjAAMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHBzOi8v
22
+ d3d3LnRpbmZvaWxzZWN1cml0eS5jb20vc2VjdXJpdHkvcmV2b2NhdGlvbl9saXN0
23
+ MA0GCSqGSIb3DQEBDQUAA4ICAQB4p1yL6e/38Dmf5HdZoSJzQ7AcM+jrD0LdMC1V
24
+ H0Y107JzZWvIB2aWH4tw4+SKGTr52OvyGFLpBv5jsWUUFssuAV971T1x41kWJSYt
25
+ tnljNguSrH6ah/pDravLxi+JGQXMBRXhkdvQKbFOfutSe9HEuZLiWUYNDYM17XJq
26
+ WmG+QhNgXliXgu4AQg+8vb1rDbu/G491GEuxbwaLyyKG8X+P5mYTBbMQbTgJkNfX
27
+ elpmFtqivFaEHs3evVGEEZRQhe8i5V0Ak2c4Or1ap/pZQf3hUIkZbw7HumyZYNWi
28
+ VJDMpObUyucv6++TNW8bAI5Oip8DGeYKibPsJ0IfYxMmRC3BmY1E3IIvAdsUHTcq
29
+ WapfQlX732+mfx/gSBpuZhdwEqjWj0xPj6l9DjQrGuhUEijfucKqyY3F280OYM1b
30
+ 2zG6cwVmh5IeR9nVv0i2KNkoc2zC8tcGpjfBBuDdXZCpow54DRJU4qQ6S0lH5ojs
31
+ aQHEEIQ9/STv9TKuc4KlMUey8W6L0Zw+xFWnkLeygaMps1PhPokSbrABQsB4C10Q
32
+ QSG/Dvvw438W/2sb9aR+skGh1oNAwJiFhLNaNALfkSXRtU16gLMPBJCi2Xqyco7V
33
+ Wh4SFQHrAbuglSi0nYgFm2SxYf/r6JRKxhVkwo8wxRiV8rDZj7WmzQoZK4GHj1u6
34
+ LXXw3g==
35
35
  -----END CERTIFICATE-----
@@ -17,18 +17,15 @@ Gem::Specification.new do |s|
17
17
  'certs/tinfoilsecurity-gems-cert.pem'
18
18
  ]
19
19
  s.signing_key = File.expand_path("~/.ssh/tinfoilsecurity-gems-key.pem") if $0 =~ /gem\z/
20
-
21
- s.rubyforge_project = 'devise-two-factor'
22
-
23
20
  s.files = `git ls-files`.split("\n").delete_if { |x| x.match('demo/*') }
24
21
  s.test_files = `git ls-files -- spec/*`.split("\n")
25
22
  s.require_paths = ['lib']
26
23
 
27
- s.add_runtime_dependency 'railties', '< 5.2'
28
- s.add_runtime_dependency 'activesupport', '< 5.2'
24
+ s.add_runtime_dependency 'railties', '< 6.2'
25
+ s.add_runtime_dependency 'activesupport', '< 6.2'
29
26
  s.add_runtime_dependency 'attr_encrypted', '>= 1.3', '< 4', '!= 2'
30
27
  s.add_runtime_dependency 'devise', '~> 4.0'
31
- s.add_runtime_dependency 'rotp', '~> 2.0'
28
+ s.add_runtime_dependency 'rotp', '~> 6.0'
32
29
 
33
30
  s.add_development_dependency 'activemodel'
34
31
  s.add_development_dependency 'appraisal'
@@ -36,5 +33,4 @@ Gem::Specification.new do |s|
36
33
  s.add_development_dependency 'rspec', '> 3'
37
34
  s.add_development_dependency 'simplecov'
38
35
  s.add_development_dependency 'faker'
39
- s.add_development_dependency 'timecop'
40
36
  end
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "railties", "~> 5.2"
6
+ gem "activesupport", "~> 5.2"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "railties", "~> 6.0"
6
+ gem "activesupport", "~> 6.0"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "railties", "~> 6.1"
6
+ gem "activesupport", "~> 6.1"
7
+
8
+ gemspec path: "../"
@@ -1,4 +1,3 @@
1
- require 'attr_encrypted'
2
1
  require 'rotp'
3
2
 
4
3
  module Devise
@@ -8,14 +7,18 @@ module Devise
8
7
  include Devise::Models::DatabaseAuthenticatable
9
8
 
10
9
  included do
11
- unless singleton_class.ancestors.include?(AttrEncrypted)
12
- extend AttrEncrypted
13
- end
14
-
15
- unless attr_encrypted?(:otp_secret)
16
- attr_encrypted :otp_secret,
17
- :key => self.otp_secret_encryption_key,
18
- :mode => :per_attribute_iv_and_salt unless self.attr_encrypted?(:otp_secret)
10
+ unless %i[otp_secret otp_secret=].all? { |attr| method_defined?(attr) }
11
+ require 'attr_encrypted'
12
+
13
+ unless singleton_class.ancestors.include?(AttrEncrypted)
14
+ extend AttrEncrypted
15
+ end
16
+
17
+ unless attr_encrypted?(:otp_secret)
18
+ attr_encrypted :otp_secret,
19
+ :key => self.otp_secret_encryption_key,
20
+ :mode => :per_attribute_iv_and_salt unless self.attr_encrypted?(:otp_secret)
21
+ end
19
22
  end
20
23
 
21
24
  attr_accessor :otp_attempt
@@ -31,8 +34,10 @@ module Devise
31
34
  otp_secret = options[:otp_secret] || self.otp_secret
32
35
  return false unless code.present? && otp_secret.present?
33
36
 
34
- totp = self.otp(otp_secret)
35
- return consume_otp! if totp.verify_with_drift(code, self.class.otp_allowed_drift)
37
+ totp = otp(otp_secret)
38
+ if totp.verify(code.gsub(/\s+/, ""), drift_behind: self.class.otp_allowed_drift, drift_ahead: self.class.otp_allowed_drift)
39
+ return consume_otp!
40
+ end
36
41
 
37
42
  false
38
43
  end
@@ -56,6 +61,7 @@ module Devise
56
61
  end
57
62
 
58
63
  def clean_up_passwords
64
+ super
59
65
  self.otp_attempt = nil
60
66
  end
61
67
 
@@ -1,3 +1,5 @@
1
+ require 'cgi'
2
+
1
3
  RSpec.shared_examples 'two_factor_authenticatable' do
2
4
  before :each do
3
5
  subject.otp_secret = subject.class.generate_otp_secret
@@ -32,12 +34,12 @@ RSpec.shared_examples 'two_factor_authenticatable' do
32
34
  let(:otp_secret) { '2z6hxkdwi3uvrnpn' }
33
35
 
34
36
  before :each do
35
- Timecop.freeze(Time.current)
37
+ travel_to(Time.now)
36
38
  subject.otp_secret = otp_secret
37
39
  end
38
40
 
39
41
  after :each do
40
- Timecop.return
42
+ travel_back
41
43
  end
42
44
 
43
45
  context 'with a stored consumed_timestep' do
@@ -54,7 +56,7 @@ RSpec.shared_examples 'two_factor_authenticatable' do
54
56
  end
55
57
 
56
58
  context 'given a previously valid OTP within the allowed drift' do
57
- let(:consumed_otp) { ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift, true) }
59
+ let(:consumed_otp) { ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift) }
58
60
 
59
61
  before do
60
62
  subject.validate_and_consume_otp!(consumed_otp)
@@ -71,23 +73,28 @@ RSpec.shared_examples 'two_factor_authenticatable' do
71
73
  expect(subject.validate_and_consume_otp!(otp)).to be true
72
74
  end
73
75
 
76
+ it 'validates a precisely correct OTP with whitespace' do
77
+ otp = ROTP::TOTP.new(otp_secret).at(Time.now)
78
+ expect(subject.validate_and_consume_otp!(otp.split("").join(" "))).to be true
79
+ end
80
+
74
81
  it 'fails a nil OTP value' do
75
82
  otp = nil
76
83
  expect(subject.validate_and_consume_otp!(otp)).to be false
77
84
  end
78
85
 
79
86
  it 'validates an OTP within the allowed drift' do
80
- otp = ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift, true)
87
+ otp = ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift)
81
88
  expect(subject.validate_and_consume_otp!(otp)).to be true
82
89
  end
83
90
 
84
91
  it 'does not validate an OTP above the allowed drift' do
85
- otp = ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift * 2, true)
92
+ otp = ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift * 2)
86
93
  expect(subject.validate_and_consume_otp!(otp)).to be false
87
94
  end
88
95
 
89
96
  it 'does not validate an OTP below the allowed drift' do
90
- otp = ROTP::TOTP.new(otp_secret).at(Time.now - subject.class.otp_allowed_drift * 2, true)
97
+ otp = ROTP::TOTP.new(otp_secret).at(Time.now - subject.class.otp_allowed_drift * 2)
91
98
  expect(subject.validate_and_consume_otp!(otp)).to be false
92
99
  end
93
100
  end
@@ -95,15 +102,15 @@ RSpec.shared_examples 'two_factor_authenticatable' do
95
102
  describe '#otp_provisioning_uri' do
96
103
  let(:otp_secret_length) { subject.class.otp_secret_length }
97
104
  let(:account) { Faker::Internet.email }
98
- let(:issuer) { "Tinfoil" }
105
+ let(:issuer) { 'Tinfoil' }
99
106
 
100
- it "should return uri with specified account" do
101
- expect(subject.otp_provisioning_uri(account)).to match(%r{otpauth://totp/#{account}\?secret=\w{#{otp_secret_length}}})
107
+ it 'should return uri with specified account' do
108
+ expect(subject.otp_provisioning_uri(account)).to match(%r{otpauth://totp/#{CGI.escape(account)}\?secret=\w{#{otp_secret_length}}})
102
109
  end
103
110
 
104
111
  it 'should return uri with issuer option' do
105
- expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{account}\?.*secret=\w{#{otp_secret_length}}(&|$)})
106
- expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{account}\?.*issuer=#{issuer}(&|$)})
112
+ expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{issuer}:#{CGI.escape(account)}\?.*secret=\w{#{otp_secret_length}}(&|$)})
113
+ expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{issuer}:#{CGI.escape(account)}\?.*issuer=#{issuer}(&|$)})
107
114
  end
108
115
  end
109
116
  end
@@ -1,2 +1,8 @@
1
+ require 'active_support/testing/time_helpers'
2
+
1
3
  require 'devise_two_factor/spec_helpers/two_factor_authenticatable_shared_examples'
2
4
  require 'devise_two_factor/spec_helpers/two_factor_backupable_shared_examples'
5
+
6
+ RSpec.configure do |config|
7
+ config.include ActiveSupport::Testing::TimeHelpers
8
+ end
@@ -12,7 +12,7 @@ module Devise
12
12
  super
13
13
  end
14
14
 
15
- fail(:not_found_in_database) unless resource
15
+ fail(Devise.paranoid ? :invalid : :not_found_in_database) unless resource
16
16
 
17
17
  # We want to cascade to the next strategy if this one fails,
18
18
  # but database authenticatable automatically halts on a bad password
@@ -12,7 +12,7 @@ module Devise
12
12
  super
13
13
  end
14
14
 
15
- fail(:not_found_in_database) unless resource
15
+ fail(Devise.paranoid ? :invalid : :not_found_in_database) unless resource
16
16
 
17
17
  # We want to cascade to the next strategy if this one fails,
18
18
  # but database authenticatable automatically halts on a bad password
@@ -1,3 +1,3 @@
1
1
  module DeviseTwoFactor
2
- VERSION = '3.0.2'.freeze
2
+ VERSION = '4.0.1'.freeze
3
3
  end
@@ -77,3 +77,23 @@ describe ::Devise::Models::TwoFactorAuthenticatable do
77
77
  end
78
78
  end
79
79
  end
80
+
81
+ describe ::Devise::Models::TwoFactorAuthenticatable do
82
+ context 'When clean_up_passwords is called ' do
83
+ subject { TwoFactorAuthenticatableDouble.new }
84
+ before :each do
85
+ subject.otp_attempt = 'foo'
86
+ subject.password_confirmation = 'foo'
87
+ end
88
+ it 'otp_attempt should be nill' do
89
+ subject.clean_up_passwords
90
+ expect(subject.otp_attempt).to be_nil
91
+ end
92
+ it 'password_confirmation should be nill' do
93
+ subject.clean_up_passwords
94
+ expect(subject.password_confirmation).to be_nil
95
+ end
96
+ end
97
+ end
98
+
99
+
data/spec/spec_helper.rb CHANGED
@@ -19,7 +19,6 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
19
19
 
20
20
  require 'rspec'
21
21
  require 'faker'
22
- require 'timecop'
23
22
  require 'devise-two-factor'
24
23
  require 'devise_two_factor/spec_helpers'
25
24
 
data.tar.gz.sig CHANGED
Binary file
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: 3.0.2
4
+ version: 4.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Wilton
@@ -52,41 +52,41 @@ cert_chain:
52
52
  -----END CERTIFICATE-----
53
53
  - |
54
54
  -----BEGIN CERTIFICATE-----
55
- MIIGATCCA+mgAwIBAgIJAK2u0LojMCOOMA0GCSqGSIb3DQEBDQUAMIGcMQswCQYD
56
- VQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVBhbG8gQWx0bzEfMB0GA1UE
57
- ChMWVGluZm9pbCBTZWN1cml0eSwgSW5jLjEfMB0GA1UEAxMWVGluZm9pbCBTZWN1
58
- cml0eSwgSW5jLjEqMCgGCSqGSIb3DQEJARYbc3VwcG9ydEB0aW5mb2lsc2VjdXJp
59
- dHkuY29tMB4XDTE3MTAwNTIyMTIwMFoXDTE4MTAwNTIyMTIwMFowgYgxCzAJBgNV
60
- BAYTAlVTMQswCQYDVQQIEwJDQTEfMB0GA1UEChMWVGluZm9pbCBTZWN1cml0eSwg
61
- SW5jLjEdMBsGA1UEAxMUdGluZm9pbHNlY3VyaXR5LWdlbXMxLDAqBgkqhkiG9w0B
62
- CQEWHWVuZ2luZWVyc0B0aW5mb2lsc2VjdXJpdHkuY29tMIICIjANBgkqhkiG9w0B
63
- AQEFAAOCAg8AMIICCgKCAgEAzSWDR/A/vJQAi7dys4xCD7N11QQj2jJtng/15PTj
64
- k7g1fzaoDCtInA/TEcTFLUt0gqwvUHD6HF0++n9i0N8lSbivqwVGrMphBEuOzyMd
65
- nMwuJ+B4GtMTz7gaYqDtuqGkRbKG8s4fUTziG52H6Y8qrXa25vmMjN7D0eF8xYq7
66
- /caJk+BPU+EQi4DkB03Cyi/SvZvhDez3lXVVF1dD2u3FbNryVCnnbHe756+i825/
67
- E6D5P+yf+Fvd9T22niOcoPWbmkWvStiGmNU5DyOuzVuKiorQVXqUZV8Okm+02HFJ
68
- 3FhEP3guQqZzpqlKxubXxg/HHOWhmTpIrVv1V2YFY/NcYAr9YZOB4xK66quBQTQG
69
- gkjcgX8EdE1GKoNZTdZ2zYzisH2+mEZ9OkdqL3BSRtLZhobEFCwq+n1vLtk30jPl
70
- PVhUiCcdoK4rq3mOxGT8IPzILFIllFjBXps9xlWF1iUd3TdqVvVKq965IymWwNG7
71
- LRlmoSTvR7hXQ2pEMaGkz2D7U0AwvpLJJDupShtSiyKGdYi2cwdSrNbxHshO5adY
72
- ploKVKvqttzxZLdYCAYv+LRr87C2cntuUFNmPly85XQjZvg8kRV2fkPmyt9yL3lH
73
- lFhDr+E9ak1xwDsqcs5oKHVURvz65bEjDgXxOdeZBtZgzBo0XAqRLZbJIMVG3+6j
74
- O4UCAwEAAaNYMFYwCQYDVR0TBAIwADBJBgNVHR8EQjBAMD6gPKA6hjhodHRwczov
75
- L3d3dy50aW5mb2lsc2VjdXJpdHkuY29tL3NlY3VyaXR5L3Jldm9jYXRpb25fbGlz
76
- dDANBgkqhkiG9w0BAQ0FAAOCAgEAOWgFA1OGyomztWe+GvGgB1JIwPqzIhhFaSLR
77
- uXlp275fyIrue9ugflj93j346PL1y88ffbzdK5tm25ZJcCX/itacoAPMHcxQeq01
78
- IFG4+xO0C+sfpklgWzYy0wrg9iTctbpk7KKtxMroVsGWK1k8BBc/1Wi3vnYxqeNO
79
- 2z670EtC1xuiOr0xY8SDO+LuBaO6SptvnIs29RVTVxaaYToUO54nX4kxMFwSrkBP
80
- Zhe6rprP8u0tO3q4CzI+MfmXJEFOC8ABF6odZmODVJRb5dQrxsqSwN8kpTdkg0As
81
- w44Qv8VIr60YBpWzpVB90ZFkQAnJXty9LaSvc7uiTExDSFiDwNx7JEgGcjLVTGZS
82
- I1LBc63m+uhZghQzm3Pi3i6hZFm5VdaFuOYL5uNsJf5dJ4Qo+K1WwmZ7y4VpuInn
83
- uWzaz2XrvJTY3/mv3JifXdq8SUFw8RnjUyc6fQo15K1jYbgY7FqfByH0Xx9avcO3
84
- wprlcVYL0flWPzWJdJ4YwY4WZ4LvjPhxOYmE28670DIOQoSajqLS7VUqXA1psgI1
85
- UqyeEsa9DYAUXhKYFarMPfzwa/SGOMX64OkGXNsVCWj93QiwE7tOJQRELouYAHI7
86
- PaA022yxKoh+TitCDcZLQC7ewl554vH1xWicHaLNuuhy6yKmqKiVR8kqtYLrijgo
87
- ztlV910=
55
+ MIIGADCCA+igAwIBAgIIP4wV6YA6CO0wDQYJKoZIhvcNAQENBQAwgZwxCzAJBgNV
56
+ BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJUGFsbyBBbHRvMR8wHQYDVQQK
57
+ ExZUaW5mb2lsIFNlY3VyaXR5LCBJbmMuMR8wHQYDVQQDExZUaW5mb2lsIFNlY3Vy
58
+ aXR5LCBJbmMuMSowKAYJKoZIhvcNAQkBFhtzdXBwb3J0QHRpbmZvaWxzZWN1cml0
59
+ eS5jb20wHhcNMjEwNDA4MTUxODAwWhcNMjExMjI0MDUwNzAwWjCBiDELMAkGA1UE
60
+ BhMCVVMxCzAJBgNVBAgTAkNBMR8wHQYDVQQKExZUaW5mb2lsIFNlY3VyaXR5LCBJ
61
+ bmMuMR0wGwYDVQQDExR0aW5mb2lsc2VjdXJpdHktZ2VtczEsMCoGCSqGSIb3DQEJ
62
+ ARYdZW5naW5lZXJzQHRpbmZvaWxzZWN1cml0eS5jb20wggIiMA0GCSqGSIb3DQEB
63
+ AQUAA4ICDwAwggIKAoICAQDNJYNH8D+8lACLt3KzjEIPs3XVBCPaMm2eD/Xk9OOT
64
+ uDV/NqgMK0icD9MRxMUtS3SCrC9QcPocXT76f2LQ3yVJuK+rBUasymEES47PIx2c
65
+ zC4n4Hga0xPPuBpioO26oaRFsobyzh9RPOIbnYfpjyqtdrbm+YyM3sPR4XzFirv9
66
+ xomT4E9T4RCLgOQHTcLKL9K9m+EN7PeVdVUXV0Pa7cVs2vJUKedsd7vnr6Lzbn8T
67
+ oPk/7J/4W931PbaeI5yg9ZuaRa9K2IaY1TkPI67NW4qKitBVepRlXw6Sb7TYcUnc
68
+ WEQ/eC5CpnOmqUrG5tfGD8cc5aGZOkitW/VXZgVj81xgCv1hk4HjErrqq4FBNAaC
69
+ SNyBfwR0TUYqg1lN1nbNjOKwfb6YRn06R2ovcFJG0tmGhsQULCr6fW8u2TfSM+U9
70
+ WFSIJx2griureY7EZPwg/MgsUiWUWMFemz3GVYXWJR3dN2pW9Uqr3rkjKZbA0bst
71
+ GWahJO9HuFdDakQxoaTPYPtTQDC+kskkO6lKG1KLIoZ1iLZzB1Ks1vEeyE7lp1im
72
+ WgpUq+q23PFkt1gIBi/4tGvzsLZye25QU2Y+XLzldCNm+DyRFXZ+Q+bK33IveUeU
73
+ WEOv4T1qTXHAOypyzmgodVRG/PrlsSMOBfE515kG1mDMGjRcCpEtlskgxUbf7qM7
74
+ hQIDAQABo1gwVjAJBgNVHRMEAjAAMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHBzOi8v
75
+ d3d3LnRpbmZvaWxzZWN1cml0eS5jb20vc2VjdXJpdHkvcmV2b2NhdGlvbl9saXN0
76
+ MA0GCSqGSIb3DQEBDQUAA4ICAQB4p1yL6e/38Dmf5HdZoSJzQ7AcM+jrD0LdMC1V
77
+ H0Y107JzZWvIB2aWH4tw4+SKGTr52OvyGFLpBv5jsWUUFssuAV971T1x41kWJSYt
78
+ tnljNguSrH6ah/pDravLxi+JGQXMBRXhkdvQKbFOfutSe9HEuZLiWUYNDYM17XJq
79
+ WmG+QhNgXliXgu4AQg+8vb1rDbu/G491GEuxbwaLyyKG8X+P5mYTBbMQbTgJkNfX
80
+ elpmFtqivFaEHs3evVGEEZRQhe8i5V0Ak2c4Or1ap/pZQf3hUIkZbw7HumyZYNWi
81
+ VJDMpObUyucv6++TNW8bAI5Oip8DGeYKibPsJ0IfYxMmRC3BmY1E3IIvAdsUHTcq
82
+ WapfQlX732+mfx/gSBpuZhdwEqjWj0xPj6l9DjQrGuhUEijfucKqyY3F280OYM1b
83
+ 2zG6cwVmh5IeR9nVv0i2KNkoc2zC8tcGpjfBBuDdXZCpow54DRJU4qQ6S0lH5ojs
84
+ aQHEEIQ9/STv9TKuc4KlMUey8W6L0Zw+xFWnkLeygaMps1PhPokSbrABQsB4C10Q
85
+ QSG/Dvvw438W/2sb9aR+skGh1oNAwJiFhLNaNALfkSXRtU16gLMPBJCi2Xqyco7V
86
+ Wh4SFQHrAbuglSi0nYgFm2SxYf/r6JRKxhVkwo8wxRiV8rDZj7WmzQoZK4GHj1u6
87
+ LXXw3g==
88
88
  -----END CERTIFICATE-----
89
- date: 2017-11-21 00:00:00.000000000 Z
89
+ date: 2021-09-01 00:00:00.000000000 Z
90
90
  dependencies:
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: railties
@@ -94,28 +94,28 @@ dependencies:
94
94
  requirements:
95
95
  - - "<"
96
96
  - !ruby/object:Gem::Version
97
- version: '5.2'
97
+ version: '6.2'
98
98
  type: :runtime
99
99
  prerelease: false
100
100
  version_requirements: !ruby/object:Gem::Requirement
101
101
  requirements:
102
102
  - - "<"
103
103
  - !ruby/object:Gem::Version
104
- version: '5.2'
104
+ version: '6.2'
105
105
  - !ruby/object:Gem::Dependency
106
106
  name: activesupport
107
107
  requirement: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - "<"
110
110
  - !ruby/object:Gem::Version
111
- version: '5.2'
111
+ version: '6.2'
112
112
  type: :runtime
113
113
  prerelease: false
114
114
  version_requirements: !ruby/object:Gem::Requirement
115
115
  requirements:
116
116
  - - "<"
117
117
  - !ruby/object:Gem::Version
118
- version: '5.2'
118
+ version: '6.2'
119
119
  - !ruby/object:Gem::Dependency
120
120
  name: attr_encrypted
121
121
  requirement: !ruby/object:Gem::Requirement
@@ -123,12 +123,12 @@ dependencies:
123
123
  - - ">="
124
124
  - !ruby/object:Gem::Version
125
125
  version: '1.3'
126
- - - "<"
127
- - !ruby/object:Gem::Version
128
- version: '4'
129
126
  - - "!="
130
127
  - !ruby/object:Gem::Version
131
128
  version: '2'
129
+ - - "<"
130
+ - !ruby/object:Gem::Version
131
+ version: '4'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
@@ -136,12 +136,12 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '1.3'
139
- - - "<"
140
- - !ruby/object:Gem::Version
141
- version: '4'
142
139
  - - "!="
143
140
  - !ruby/object:Gem::Version
144
141
  version: '2'
142
+ - - "<"
143
+ - !ruby/object:Gem::Version
144
+ version: '4'
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: devise
147
147
  requirement: !ruby/object:Gem::Requirement
@@ -162,14 +162,14 @@ dependencies:
162
162
  requirements:
163
163
  - - "~>"
164
164
  - !ruby/object:Gem::Version
165
- version: '2.0'
165
+ version: '6.0'
166
166
  type: :runtime
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - "~>"
171
171
  - !ruby/object:Gem::Version
172
- version: '2.0'
172
+ version: '6.0'
173
173
  - !ruby/object:Gem::Dependency
174
174
  name: activemodel
175
175
  requirement: !ruby/object:Gem::Requirement
@@ -254,29 +254,15 @@ dependencies:
254
254
  - - ">="
255
255
  - !ruby/object:Gem::Version
256
256
  version: '0'
257
- - !ruby/object:Gem::Dependency
258
- name: timecop
259
- requirement: !ruby/object:Gem::Requirement
260
- requirements:
261
- - - ">="
262
- - !ruby/object:Gem::Version
263
- version: '0'
264
- type: :development
265
- prerelease: false
266
- version_requirements: !ruby/object:Gem::Requirement
267
- requirements:
268
- - - ">="
269
- - !ruby/object:Gem::Version
270
- version: '0'
271
257
  description: Barebones two-factor authentication with Devise
272
258
  email: engineers@tinfoilsecurity.com
273
259
  executables: []
274
260
  extensions: []
275
261
  extra_rdoc_files: []
276
262
  files:
263
+ - ".github/workflows/ci.yml"
277
264
  - ".gitignore"
278
265
  - ".rspec"
279
- - ".travis.yml"
280
266
  - Appraisals
281
267
  - CHANGELOG.md
282
268
  - CONTRIBUTING.md
@@ -288,10 +274,13 @@ files:
288
274
  - certs/tinfoil-cacert.pem
289
275
  - certs/tinfoilsecurity-gems-cert.pem
290
276
  - devise-two-factor.gemspec
291
- - gemfiles/rails_4_1.gemfile
292
- - gemfiles/rails_4_2.gemfile
293
- - gemfiles/rails_5_0.gemfile
294
- - gemfiles/rails_5_1.gemfile
277
+ - gemfiles/rails_4.1.gemfile
278
+ - gemfiles/rails_4.2.gemfile
279
+ - gemfiles/rails_5.0.gemfile
280
+ - gemfiles/rails_5.1.gemfile
281
+ - gemfiles/rails_5.2.gemfile
282
+ - gemfiles/rails_6.0.gemfile
283
+ - gemfiles/rails_6.1.gemfile
295
284
  - lib/devise-two-factor.rb
296
285
  - lib/devise_two_factor/models.rb
297
286
  - lib/devise_two_factor/models/two_factor_authenticatable.rb
@@ -326,8 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
326
315
  - !ruby/object:Gem::Version
327
316
  version: '0'
328
317
  requirements: []
329
- rubyforge_project: devise-two-factor
330
- rubygems_version: 2.6.10
318
+ rubygems_version: 3.0.3
331
319
  signing_key:
332
320
  specification_version: 4
333
321
  summary: Barebones two-factor authentication with Devise
metadata.gz.sig CHANGED
Binary file
data/.travis.yml DELETED
@@ -1,28 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- cache: bundler
4
- before_install:
5
- - gem update --system
6
- - gem update bundler
7
- gemfile:
8
- - Gemfile
9
- - gemfiles/rails_4_1.gemfile
10
- - gemfiles/rails_4_2.gemfile
11
- - gemfiles/rails_5_0.gemfile
12
- - gemfiles/rails_5_1.gemfile
13
- rvm:
14
- - "2.1"
15
- - "2.2"
16
- - "2.3.4"
17
- - "2.4.0"
18
- - "2.4.1"
19
- matrix:
20
- exclude:
21
- - rvm: "2.1"
22
- gemfile: gemfiles/rails_5_0.gemfile
23
- - rvm: "2.2"
24
- gemfile: gemfiles/rails_5_0.gemfile
25
- - rvm: "2.1"
26
- gemfile: gemfiles/rails_5_1.gemfile
27
- - rvm: "2.2"
28
- gemfile: gemfiles/rails_5_1.gemfile