devise-two-factor 3.1.0 → 4.0.0

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
  SHA256:
3
- metadata.gz: 12a32c4d2067b65a19376f7d98480e89975091a9b57eddd01b7bd8a036eae7bb
4
- data.tar.gz: 46c843c0e7aeaa0e2432a667195bef8f92eabfc1e7940c9f9e067a3c08fe8797
3
+ metadata.gz: 33ab6513476203a5a4135af19c1f3bbddeeed83fb2ed8bf3a74c2afe2e74be9b
4
+ data.tar.gz: 16068a92b6b20aa06108cb0e3cd294dc5c98c19563311d024dcfc7e0573030ad
5
5
  SHA512:
6
- metadata.gz: 6de2e060514bfcea44bde7fde4c63bc8ab5f0ad934f4d69e3224fdf9534e9c452abc7bb6994d964cd0de61a244ba57e7c400979e07b81c3c2a93d1745aef997d
7
- data.tar.gz: 867896645165eca78879f02ace0acffedd86f1b32cd38e221630ac9e3bf7f47fec71d6cfa90f5fb16b7a2241b63ca004a33ac598bb60df98bd21601bfda5e16f
6
+ metadata.gz: 258cd2abf3bc9beb80c0f9fc596b33055efa24ca53177847fbab5a38b80a220e322a2739303b30128c356000dabd708bcc77e835dacecee2e3c9fe51b66c2b33
7
+ data.tar.gz: 940c49c9b2cbea4832ee8f66c39b26c1c6ad45d09dc054cf0c54d0be823219e18ad4ef7ca12dc388e2eec319534be0d880b5f9d3e2eb5fcace86ce6b9008e960
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 4.0.0
6
+ - Update ROTP
7
+ - Add Rails 6.1 support
8
+ - Remove timecop dependency
9
+ - Clarify changes in project ownership
10
+ - Bugfixes & cleanup
11
+
12
+ ## 3.1.0
13
+ - Add Rails 6.0 support
14
+ - New gem signing certificate
15
+ - Fix paranoid-mode being ignored
16
+
17
+ ## 3.0.3
18
+ - Add Rails 5.2 support
19
+
5
20
  ## 3.0.2
6
21
  - Add Rails 5.1 support
7
22
 
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,9 +1,9 @@
1
1
  # Devise-Two-Factor Authentication
2
- By [Tinfoil Security](https://www.tinfoilsecurity.com/). Interested in [working with us](https://www.tinfoilsecurity.com/jobs)? We're hiring!
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
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) 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
@@ -53,7 +53,13 @@ This generator will add a few columns to the specified model:
53
53
  * consumed_timestep
54
54
  * otp_required_for_login
55
55
 
56
- 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.
57
63
 
58
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.
59
65
 
@@ -85,7 +91,7 @@ def configure_permitted_parameters
85
91
  end
86
92
  ```
87
93
 
88
- **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.**
89
95
 
90
96
  ## Designing Your Workflow
91
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.
@@ -95,7 +101,7 @@ There are two key workflows you'll have to think about:
95
101
  1. Logging in with two-factor authentication
96
102
  2. Enabling two-factor authentication for a given user
97
103
 
98
- 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).
99
105
 
100
106
 
101
107
  ### Logging In
@@ -108,7 +114,7 @@ Logging in with two-factor authentication works extremely similarly to regular d
108
114
  These parameters can be submitted to the standard Devise login route, and the strategy will handle the authentication of the user for you.
109
115
 
110
116
  ### Disabling Automatic Login After Password Resets
111
- 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.
112
118
 
113
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`).
114
120
 
@@ -142,7 +148,13 @@ If you instead to decide to send the one-time password to the user directly, suc
142
148
  current_user.current_otp
143
149
  ```
144
150
 
145
- 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
+ ```
146
158
 
147
159
  However you decide to handle enrollment, there are a few important considerations to be made:
148
160
 
@@ -1,9 +1,9 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIIGADCCA+igAwIBAgIIBr+qGSyQe7MwDQYJKoZIhvcNAQENBQAwgZwxCzAJBgNV
2
+ MIIGADCCA+igAwIBAgIIP4wV6YA6CO0wDQYJKoZIhvcNAQENBQAwgZwxCzAJBgNV
3
3
  BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJUGFsbyBBbHRvMR8wHQYDVQQK
4
4
  ExZUaW5mb2lsIFNlY3VyaXR5LCBJbmMuMR8wHQYDVQQDExZUaW5mb2lsIFNlY3Vy
5
5
  aXR5LCBJbmMuMSowKAYJKoZIhvcNAQkBFhtzdXBwb3J0QHRpbmZvaWxzZWN1cml0
6
- eS5jb20wHhcNMTkwODA3MTkwMjAwWhcNMjAwODA3MTkwMjAwWjCBiDELMAkGA1UE
6
+ eS5jb20wHhcNMjEwNDA4MTUxODAwWhcNMjExMjI0MDUwNzAwWjCBiDELMAkGA1UE
7
7
  BhMCVVMxCzAJBgNVBAgTAkNBMR8wHQYDVQQKExZUaW5mb2lsIFNlY3VyaXR5LCBJ
8
8
  bmMuMR0wGwYDVQQDExR0aW5mb2lsc2VjdXJpdHktZ2VtczEsMCoGCSqGSIb3DQEJ
9
9
  ARYdZW5naW5lZXJzQHRpbmZvaWxzZWN1cml0eS5jb20wggIiMA0GCSqGSIb3DQEB
@@ -20,16 +20,16 @@ WgpUq+q23PFkt1gIBi/4tGvzsLZye25QU2Y+XLzldCNm+DyRFXZ+Q+bK33IveUeU
20
20
  WEOv4T1qTXHAOypyzmgodVRG/PrlsSMOBfE515kG1mDMGjRcCpEtlskgxUbf7qM7
21
21
  hQIDAQABo1gwVjAJBgNVHRMEAjAAMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHBzOi8v
22
22
  d3d3LnRpbmZvaWxzZWN1cml0eS5jb20vc2VjdXJpdHkvcmV2b2NhdGlvbl9saXN0
23
- MA0GCSqGSIb3DQEBDQUAA4ICAQAiW9gcR0TTaxsK1DaHZ9U9VxP0dhtWKyTcjDnE
24
- BHlaayjrEmmQHmEtDEFOkLYOo20LpMFaogxcSHBYto5Z3XYfU9ZPuaY6rGVFhXeq
25
- mrQn6O0iOxzNOHLSZTgEjQTc2gJg1p1CYSxapla53ivW5v01dNcS1XJE/HFHQttI
26
- gXdNb53g7XW/c1Be5MvtQKZHsYGNANE+NUUOIFMp29PI1iXBVZVm2PSYL4XlGgQi
27
- 2cg3tU2TK6+wLul5ZMMvNrOgjaWcbqgW976hUAE03OgR5GDy4M3LfYOs8OJNsktG
28
- dtpfft6WroUoiqzDCNz85fbLqhY0vwPNJxK/wFHvxTJ2MKL/BdOha8gIV2o5HPTC
29
- cBpZx2C8FyUKAZfuXwTVkMtPbhFowjPNQN4TNl5N6DRtLnb1PDn9LOXHCPd+0V2b
30
- ssxu8B1+kf9IyrKBhlqKWSoLdaPboz5FunBUj6nkbXz2VlCkqbRIAFaTtmMJjjWR
31
- I0Fgx1CAbDjnDvf/hYrjPAvwLOcQ117Tm3Wk/3MP78CwmZoFHRrBw68Ir5mcLrQy
32
- L71AbBqGd3i+azsNXMmm11ZZetYzbIy6kc9g9MFHd+3xooJpU7eRpm+tyRLKX/qu
33
- /9iBhU0HVz2daNTk8LdQtzGqff8Dj0qB4sBndVsTW1JxKRP8E3jeLBT4EBGsy9OL
34
- 5aBXTA==
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', '< 6.1'
28
- s.add_runtime_dependency 'activesupport', '< 6.1'
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
@@ -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, 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)
@@ -77,17 +79,17 @@ RSpec.shared_examples 'two_factor_authenticatable' do
77
79
  end
78
80
 
79
81
  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)
82
+ otp = ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift)
81
83
  expect(subject.validate_and_consume_otp!(otp)).to be true
82
84
  end
83
85
 
84
86
  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)
87
+ otp = ROTP::TOTP.new(otp_secret).at(Time.now + subject.class.otp_allowed_drift * 2)
86
88
  expect(subject.validate_and_consume_otp!(otp)).to be false
87
89
  end
88
90
 
89
91
  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)
92
+ otp = ROTP::TOTP.new(otp_secret).at(Time.now - subject.class.otp_allowed_drift * 2)
91
93
  expect(subject.validate_and_consume_otp!(otp)).to be false
92
94
  end
93
95
  end
@@ -95,15 +97,15 @@ RSpec.shared_examples 'two_factor_authenticatable' do
95
97
  describe '#otp_provisioning_uri' do
96
98
  let(:otp_secret_length) { subject.class.otp_secret_length }
97
99
  let(:account) { Faker::Internet.email }
98
- let(:issuer) { "Tinfoil" }
100
+ let(:issuer) { 'Tinfoil' }
99
101
 
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}}})
102
+ it 'should return uri with specified account' do
103
+ expect(subject.otp_provisioning_uri(account)).to match(%r{otpauth://totp/#{CGI.escape(account)}\?secret=\w{#{otp_secret_length}}})
102
104
  end
103
105
 
104
106
  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}(&|$)})
107
+ expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{issuer}:#{CGI.escape(account)}\?.*secret=\w{#{otp_secret_length}}(&|$)})
108
+ expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{issuer}:#{CGI.escape(account)}\?.*issuer=#{issuer}(&|$)})
107
109
  end
108
110
  end
109
111
  end
@@ -1,3 +1,3 @@
1
1
  module DeviseTwoFactor
2
- VERSION = '3.1.0'.freeze
2
+ VERSION = '4.0.0'.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,14 +19,15 @@ $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'
24
+ require 'active_support/testing/time_helpers'
25
25
 
26
26
  # Requires supporting files with custom matchers and macros, etc,
27
27
  # in ./support/ and its subdirectories.
28
28
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
29
29
 
30
30
  RSpec.configure do |config|
31
+ config.include ActiveSupport::Testing::TimeHelpers
31
32
  config.order = 'random'
32
33
  end
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.1.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Wilton
@@ -52,11 +52,11 @@ cert_chain:
52
52
  -----END CERTIFICATE-----
53
53
  - |
54
54
  -----BEGIN CERTIFICATE-----
55
- MIIGADCCA+igAwIBAgIIBr+qGSyQe7MwDQYJKoZIhvcNAQENBQAwgZwxCzAJBgNV
55
+ MIIGADCCA+igAwIBAgIIP4wV6YA6CO0wDQYJKoZIhvcNAQENBQAwgZwxCzAJBgNV
56
56
  BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJUGFsbyBBbHRvMR8wHQYDVQQK
57
57
  ExZUaW5mb2lsIFNlY3VyaXR5LCBJbmMuMR8wHQYDVQQDExZUaW5mb2lsIFNlY3Vy
58
58
  aXR5LCBJbmMuMSowKAYJKoZIhvcNAQkBFhtzdXBwb3J0QHRpbmZvaWxzZWN1cml0
59
- eS5jb20wHhcNMTkwODA3MTkwMjAwWhcNMjAwODA3MTkwMjAwWjCBiDELMAkGA1UE
59
+ eS5jb20wHhcNMjEwNDA4MTUxODAwWhcNMjExMjI0MDUwNzAwWjCBiDELMAkGA1UE
60
60
  BhMCVVMxCzAJBgNVBAgTAkNBMR8wHQYDVQQKExZUaW5mb2lsIFNlY3VyaXR5LCBJ
61
61
  bmMuMR0wGwYDVQQDExR0aW5mb2lsc2VjdXJpdHktZ2VtczEsMCoGCSqGSIb3DQEJ
62
62
  ARYdZW5naW5lZXJzQHRpbmZvaWxzZWN1cml0eS5jb20wggIiMA0GCSqGSIb3DQEB
@@ -73,20 +73,20 @@ cert_chain:
73
73
  WEOv4T1qTXHAOypyzmgodVRG/PrlsSMOBfE515kG1mDMGjRcCpEtlskgxUbf7qM7
74
74
  hQIDAQABo1gwVjAJBgNVHRMEAjAAMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHBzOi8v
75
75
  d3d3LnRpbmZvaWxzZWN1cml0eS5jb20vc2VjdXJpdHkvcmV2b2NhdGlvbl9saXN0
76
- MA0GCSqGSIb3DQEBDQUAA4ICAQAiW9gcR0TTaxsK1DaHZ9U9VxP0dhtWKyTcjDnE
77
- BHlaayjrEmmQHmEtDEFOkLYOo20LpMFaogxcSHBYto5Z3XYfU9ZPuaY6rGVFhXeq
78
- mrQn6O0iOxzNOHLSZTgEjQTc2gJg1p1CYSxapla53ivW5v01dNcS1XJE/HFHQttI
79
- gXdNb53g7XW/c1Be5MvtQKZHsYGNANE+NUUOIFMp29PI1iXBVZVm2PSYL4XlGgQi
80
- 2cg3tU2TK6+wLul5ZMMvNrOgjaWcbqgW976hUAE03OgR5GDy4M3LfYOs8OJNsktG
81
- dtpfft6WroUoiqzDCNz85fbLqhY0vwPNJxK/wFHvxTJ2MKL/BdOha8gIV2o5HPTC
82
- cBpZx2C8FyUKAZfuXwTVkMtPbhFowjPNQN4TNl5N6DRtLnb1PDn9LOXHCPd+0V2b
83
- ssxu8B1+kf9IyrKBhlqKWSoLdaPboz5FunBUj6nkbXz2VlCkqbRIAFaTtmMJjjWR
84
- I0Fgx1CAbDjnDvf/hYrjPAvwLOcQ117Tm3Wk/3MP78CwmZoFHRrBw68Ir5mcLrQy
85
- L71AbBqGd3i+azsNXMmm11ZZetYzbIy6kc9g9MFHd+3xooJpU7eRpm+tyRLKX/qu
86
- /9iBhU0HVz2daNTk8LdQtzGqff8Dj0qB4sBndVsTW1JxKRP8E3jeLBT4EBGsy9OL
87
- 5aBXTA==
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: 2019-08-07 00:00:00.000000000 Z
89
+ date: 2021-04-08 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: '6.1'
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: '6.1'
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: '6.1'
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: '6.1'
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,20 +254,6 @@ 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: []
@@ -328,8 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
328
314
  - !ruby/object:Gem::Version
329
315
  version: '0'
330
316
  requirements: []
331
- rubyforge_project: devise-two-factor
332
- rubygems_version: 2.7.6.2
317
+ rubygems_version: 3.0.3
333
318
  signing_key:
334
319
  specification_version: 4
335
320
  summary: Barebones two-factor authentication with Devise
metadata.gz.sig CHANGED
Binary file