devise-two-factor 4.1.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +3 -18
- data/.markdownlint.json +6 -0
- data/CHANGELOG.md +15 -0
- data/README.md +109 -63
- data/SECURITY.md +5 -0
- data/UPGRADING.md +218 -2
- data/devise-two-factor.gemspec +4 -7
- data/gemfiles/rails_7.0.gemfile +2 -2
- data/gemfiles/{rails_4.1.gemfile → rails_7.1.gemfile} +2 -2
- data/lib/devise-two-factor.rb +11 -5
- data/lib/devise_two_factor/models/two_factor_authenticatable.rb +32 -17
- data/lib/devise_two_factor/models/two_factor_backupable.rb +3 -2
- data/lib/devise_two_factor/spec_helpers/two_factor_authenticatable_shared_examples.rb +6 -18
- data/lib/devise_two_factor/spec_helpers/two_factor_backupable_shared_examples.rb +2 -2
- data/lib/devise_two_factor/strategies/two_factor_authenticatable.rb +1 -1
- data/lib/devise_two_factor/strategies/two_factor_backupable.rb +0 -3
- data/lib/devise_two_factor/version.rb +1 -1
- data/lib/generators/devise_two_factor/devise_two_factor_generator.rb +2 -7
- data/spec/devise/models/two_factor_authenticatable_spec.rb +11 -69
- data/spec/devise/models/two_factor_backupable_spec.rb +11 -2
- data/spec/spec_helper.rb +0 -1
- data.tar.gz.sig +0 -0
- metadata +15 -57
- metadata.gz.sig +0 -0
- data/gemfiles/rails_4.2.gemfile +0 -8
- data/gemfiles/rails_5.0.gemfile +0 -8
- data/gemfiles/rails_5.1.gemfile +0 -8
- data/gemfiles/rails_5.2.gemfile +0 -8
- data/gemfiles/rails_6.0.gemfile +0 -8
- data/gemfiles/rails_6.1.gemfile +0 -8
data/gemfiles/rails_7.0.gemfile
CHANGED
data/lib/devise-two-factor.rb
CHANGED
@@ -3,20 +3,26 @@ require 'devise_two_factor/models'
|
|
3
3
|
require 'devise_two_factor/strategies'
|
4
4
|
|
5
5
|
module Devise
|
6
|
-
# The length of generated OTP
|
6
|
+
# The length of randomly generated OTP shared secret (in bytes).
|
7
|
+
# The secrets will be base32-encoded and have a length 1.6 times the configured value.
|
7
8
|
mattr_accessor :otp_secret_length
|
8
|
-
@@otp_secret_length =
|
9
|
+
@@otp_secret_length = 20
|
9
10
|
|
10
11
|
# The number of seconds before and after the current
|
11
12
|
# time for which codes will be accepted
|
12
13
|
mattr_accessor :otp_allowed_drift
|
13
14
|
@@otp_allowed_drift = 30
|
14
15
|
|
15
|
-
# The key used to encrypt OTP secrets in the database
|
16
|
+
# The key used to encrypt OTP secrets in the database in legacy installs.
|
16
17
|
mattr_accessor :otp_secret_encryption_key
|
17
18
|
@@otp_secret_encryption_key = nil
|
18
19
|
|
19
|
-
#
|
20
|
+
# These options are passed to the Rails 7+ encrypted attribute
|
21
|
+
mattr_accessor :otp_encrypted_attribute_options
|
22
|
+
@@otp_encrypted_attribute_options = {}
|
23
|
+
|
24
|
+
# The length of randomly generated OTP backup codes (in bytes).
|
25
|
+
# The codes will be hex-encoded and have a length twice the configured value.
|
20
26
|
mattr_accessor :otp_backup_code_length
|
21
27
|
@@otp_backup_code_length = 16
|
22
28
|
|
@@ -27,7 +33,7 @@ module Devise
|
|
27
33
|
end
|
28
34
|
|
29
35
|
Devise.add_module(:two_factor_authenticatable, :route => :session, :strategy => true,
|
30
|
-
:controller => :sessions, :model => true)
|
36
|
+
:controller => :sessions, :model => true, :insert_at => 0)
|
31
37
|
|
32
38
|
Devise.add_module(:two_factor_backupable, :route => :session, :strategy => true,
|
33
39
|
:controller => :sessions, :model => true)
|
@@ -7,25 +7,28 @@ module Devise
|
|
7
7
|
include Devise::Models::DatabaseAuthenticatable
|
8
8
|
|
9
9
|
included do
|
10
|
-
|
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
|
22
|
-
end
|
23
|
-
|
10
|
+
encrypts :otp_secret, **splattable_encrypted_attr_options
|
24
11
|
attr_accessor :otp_attempt
|
25
12
|
end
|
26
13
|
|
14
|
+
def otp_secret
|
15
|
+
# return the OTP secret stored as a Rails encrypted attribute if it
|
16
|
+
# exists. Otherwise return OTP secret stored by the `attr_encrypted` gem
|
17
|
+
return self[:otp_secret] if self[:otp_secret]
|
18
|
+
|
19
|
+
legacy_otp_secret
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Decrypt and return the `encrypted_otp_secret` attribute which was used in
|
24
|
+
# prior versions of devise-two-factor
|
25
|
+
# See: # https://github.com/tinfoil/devise-two-factor/blob/main/UPGRADING.md
|
26
|
+
def legacy_otp_secret
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
27
30
|
def self.required_fields(klass)
|
28
|
-
[:
|
31
|
+
[:otp_secret, :consumed_timestep]
|
29
32
|
end
|
30
33
|
|
31
34
|
# This defaults to the model's otp_secret
|
@@ -78,7 +81,8 @@ module Devise
|
|
78
81
|
def consume_otp!
|
79
82
|
if self.consumed_timestep != current_otp_timestep
|
80
83
|
self.consumed_timestep = current_otp_timestep
|
81
|
-
|
84
|
+
save!(validate: false)
|
85
|
+
return true
|
82
86
|
end
|
83
87
|
|
84
88
|
false
|
@@ -87,10 +91,21 @@ module Devise
|
|
87
91
|
module ClassMethods
|
88
92
|
Devise::Models.config(self, :otp_secret_length,
|
89
93
|
:otp_allowed_drift,
|
94
|
+
:otp_encrypted_attribute_options,
|
90
95
|
:otp_secret_encryption_key)
|
91
96
|
|
97
|
+
# Geneartes an OTP secret of the specified length, returning it after Base32 encoding.
|
92
98
|
def generate_otp_secret(otp_secret_length = self.otp_secret_length)
|
93
|
-
ROTP::Base32.
|
99
|
+
ROTP::Base32.random(otp_secret_length)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Return value will be splatted with ** so return a version of the
|
103
|
+
# encrypted attribute options which is always a Hash.
|
104
|
+
# @return [Hash]
|
105
|
+
def splattable_encrypted_attr_options
|
106
|
+
return {} if otp_encrypted_attribute_options.nil?
|
107
|
+
|
108
|
+
otp_encrypted_attribute_options
|
94
109
|
end
|
95
110
|
end
|
96
111
|
end
|
@@ -20,7 +20,7 @@ module Devise
|
|
20
20
|
code_length = self.class.otp_backup_code_length
|
21
21
|
|
22
22
|
number_of_codes.times do
|
23
|
-
codes << SecureRandom.hex(code_length
|
23
|
+
codes << SecureRandom.hex(code_length)
|
24
24
|
end
|
25
25
|
|
26
26
|
hashed_codes = codes.map { |code| Devise::Encryptor.digest(self.class, code) }
|
@@ -30,7 +30,7 @@ module Devise
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# Returns true and invalidates the given code
|
33
|
-
#
|
33
|
+
# if that code is a valid backup code.
|
34
34
|
def invalidate_otp_backup_code!(code)
|
35
35
|
codes = self.otp_backup_codes || []
|
36
36
|
|
@@ -39,6 +39,7 @@ module Devise
|
|
39
39
|
|
40
40
|
codes.delete(backup_code)
|
41
41
|
self.otp_backup_codes = codes
|
42
|
+
save!(validate: false)
|
42
43
|
return true
|
43
44
|
end
|
44
45
|
|
@@ -8,25 +8,13 @@ RSpec.shared_examples 'two_factor_authenticatable' do
|
|
8
8
|
|
9
9
|
describe 'required_fields' do
|
10
10
|
it 'should have the attr_encrypted fields for otp_secret' do
|
11
|
-
expect(Devise::Models::TwoFactorAuthenticatable.required_fields(subject.class)).to contain_exactly(:
|
11
|
+
expect(Devise::Models::TwoFactorAuthenticatable.required_fields(subject.class)).to contain_exactly(:otp_secret, :consumed_timestep)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '#otp_secret' do
|
16
|
-
it 'should be of the
|
17
|
-
expect(subject.otp_secret.length).to eq(subject.class.otp_secret_length)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'stores the encrypted otp_secret' do
|
21
|
-
expect(subject.encrypted_otp_secret).to_not be_nil
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'stores an iv for otp_secret' do
|
25
|
-
expect(subject.encrypted_otp_secret_iv).to_not be_nil
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'stores a salt for otp_secret' do
|
29
|
-
expect(subject.encrypted_otp_secret_salt).to_not be_nil
|
16
|
+
it 'should be of the expected length' do
|
17
|
+
expect(subject.otp_secret.length).to eq(subject.class.otp_secret_length*8/5)
|
30
18
|
end
|
31
19
|
end
|
32
20
|
|
@@ -137,15 +125,15 @@ RSpec.shared_examples 'two_factor_authenticatable' do
|
|
137
125
|
|
138
126
|
describe '#otp_provisioning_uri' do
|
139
127
|
let(:otp_secret_length) { subject.class.otp_secret_length }
|
140
|
-
let(:account) {
|
128
|
+
let(:account) { 'user@host.example' }
|
141
129
|
let(:issuer) { 'Tinfoil' }
|
142
130
|
|
143
131
|
it 'should return uri with specified account' do
|
144
|
-
expect(subject.otp_provisioning_uri(account)).to match(%r{otpauth://totp/#{CGI.escape(account)}\?secret=\w{#{otp_secret_length}}})
|
132
|
+
expect(subject.otp_provisioning_uri(account)).to match(%r{otpauth://totp/#{CGI.escape(account)}\?secret=\w{#{otp_secret_length*8/5}}})
|
145
133
|
end
|
146
134
|
|
147
135
|
it 'should return uri with issuer option' do
|
148
|
-
expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{issuer}:#{CGI.escape(account)}\?.*secret=\w{#{otp_secret_length}}(&|$)})
|
136
|
+
expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{issuer}:#{CGI.escape(account)}\?.*secret=\w{#{otp_secret_length*8/5}}(&|$)})
|
149
137
|
expect(subject.otp_provisioning_uri(account, issuer: issuer)).to match(%r{otpauth://totp/#{issuer}:#{CGI.escape(account)}\?.*issuer=#{issuer}(&|$)})
|
150
138
|
end
|
151
139
|
end
|
@@ -17,7 +17,7 @@ RSpec.shared_examples 'two_factor_backupable' do
|
|
17
17
|
|
18
18
|
it 'generates recovery codes of the correct length' do
|
19
19
|
@plaintext_codes.each do |code|
|
20
|
-
expect(code.length).to eq(subject.class.otp_backup_code_length)
|
20
|
+
expect(code.length).to eq(subject.class.otp_backup_code_length*2)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -34,7 +34,7 @@ RSpec.shared_examples 'two_factor_backupable' do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
context 'with existing recovery codes' do
|
37
|
-
let(:old_codes) {
|
37
|
+
let(:old_codes) { ['adam', 'betty', 'charles'] }
|
38
38
|
let(:old_codes_hashed) { old_codes.map { |x| Devise::Encryptor.digest(subject.class, x) } }
|
39
39
|
|
40
40
|
before do
|
@@ -21,7 +21,7 @@ module Devise
|
|
21
21
|
|
22
22
|
def validate_otp(resource)
|
23
23
|
return true unless resource.otp_required_for_login
|
24
|
-
return if params[scope]['otp_attempt'].nil?
|
24
|
+
return if params[scope].nil? || params[scope]['otp_attempt'].nil?
|
25
25
|
resource.validate_and_consume_otp!(params[scope]['otp_attempt'])
|
26
26
|
end
|
27
27
|
end
|
@@ -6,9 +6,6 @@ module Devise
|
|
6
6
|
resource = mapping.to.find_for_database_authentication(authentication_hash)
|
7
7
|
|
8
8
|
if validate(resource) { resource.invalidate_otp_backup_code!(params[scope]['otp_attempt']) }
|
9
|
-
# Devise fails to authenticate invalidated resources, but if we've
|
10
|
-
# gotten here, the object changed (Since we deleted a recovery code)
|
11
|
-
resource.save!
|
12
9
|
super
|
13
10
|
end
|
14
11
|
|
@@ -3,8 +3,6 @@ require 'rails/generators'
|
|
3
3
|
module DeviseTwoFactor
|
4
4
|
module Generators
|
5
5
|
class DeviseTwoFactorGenerator < Rails::Generators::NamedBase
|
6
|
-
argument :encryption_key_env, :type => :string, :required => true
|
7
|
-
|
8
6
|
desc 'Creates a migration to add the required attributes to NAME, and ' \
|
9
7
|
'adds the necessary Devise directives to the model'
|
10
8
|
|
@@ -19,9 +17,7 @@ module DeviseTwoFactor
|
|
19
17
|
def create_devise_two_factor_migration
|
20
18
|
migration_arguments = [
|
21
19
|
"add_devise_two_factor_to_#{plural_name}",
|
22
|
-
"
|
23
|
-
"encrypted_otp_secret_iv:string",
|
24
|
-
"encrypted_otp_secret_salt:string",
|
20
|
+
"otp_secret:string",
|
25
21
|
"consumed_timestep:integer",
|
26
22
|
"otp_required_for_login:boolean"
|
27
23
|
]
|
@@ -51,8 +47,7 @@ module DeviseTwoFactor
|
|
51
47
|
indent_depth = class_path.size
|
52
48
|
|
53
49
|
content = [
|
54
|
-
"devise :two_factor_authenticatable
|
55
|
-
" :otp_secret_encryption_key => ENV['#{encryption_key_env}']\n"
|
50
|
+
"devise :two_factor_authenticatable"
|
56
51
|
]
|
57
52
|
|
58
53
|
content << "attr_accessible :otp_attempt\n" if needs_attr_accessible?
|
@@ -6,91 +6,33 @@ class TwoFactorAuthenticatableDouble
|
|
6
6
|
include ::ActiveModel::Validations::Callbacks
|
7
7
|
extend ::Devise::Models
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
attr_accessor :consumed_timestep
|
14
|
-
|
15
|
-
def save(validate)
|
16
|
-
# noop for testing
|
17
|
-
true
|
9
|
+
# stub out the ::ActiveRecord::Encryption::EncryptableRecord API
|
10
|
+
attr_accessor :otp_secret
|
11
|
+
def self.encrypts(*attrs)
|
12
|
+
nil
|
18
13
|
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class TwoFactorAuthenticatableWithCustomizeAttrEncryptedDouble
|
22
|
-
extend ::ActiveModel::Callbacks
|
23
|
-
include ::ActiveModel::Validations::Callbacks
|
24
|
-
|
25
|
-
# like https://github.com/tinfoil/devise-two-factor/blob/cf73e52043fbe45b74d68d02bc859522ad22fe73/UPGRADING.md#guide-to-upgrading-from-2x-to-3x
|
26
|
-
extend ::AttrEncrypted
|
27
|
-
attr_encrypted :otp_secret,
|
28
|
-
:key => 'test-key'*8,
|
29
|
-
:mode => :per_attribute_iv_and_salt,
|
30
|
-
:algorithm => 'aes-256-cbc'
|
31
|
-
|
32
|
-
extend ::Devise::Models
|
33
14
|
|
34
15
|
define_model_callbacks :update
|
35
16
|
|
36
|
-
devise :two_factor_authenticatable
|
17
|
+
devise :two_factor_authenticatable
|
37
18
|
|
38
19
|
attr_accessor :consumed_timestep
|
39
20
|
|
40
|
-
def save(
|
21
|
+
def save!(_)
|
41
22
|
# noop for testing
|
42
23
|
true
|
43
24
|
end
|
44
25
|
end
|
45
26
|
|
46
27
|
describe ::Devise::Models::TwoFactorAuthenticatable do
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
it_behaves_like 'two_factor_authenticatable'
|
28
|
+
it 'should be inserted prior to other devise modules' do
|
29
|
+
expect(Devise::ALL.first).to eq(:two_factor_authenticatable)
|
51
30
|
end
|
52
|
-
end
|
53
31
|
|
54
|
-
describe ::Devise::Models::TwoFactorAuthenticatable do
|
55
32
|
context 'When included in a class' do
|
56
|
-
subject {
|
33
|
+
subject { TwoFactorAuthenticatableDouble.new }
|
57
34
|
|
58
35
|
it_behaves_like 'two_factor_authenticatable'
|
59
|
-
|
60
|
-
before :each do
|
61
|
-
subject.otp_secret = subject.class.generate_otp_secret
|
62
|
-
subject.consumed_timestep = nil
|
63
|
-
end
|
64
|
-
|
65
|
-
describe 'otp_secret options' do
|
66
|
-
it 'should be of the key' do
|
67
|
-
if attr_encrypted_is_rails_seven_compatible?
|
68
|
-
expect(subject.attr_encrypted_encrypted_attributes[:otp_secret][:key]).to eq('test-key'*8)
|
69
|
-
else
|
70
|
-
expect(subject.encrypted_attributes[:otp_secret][:key]).to eq('test-key'*8)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'should be of the mode' do
|
75
|
-
if attr_encrypted_is_rails_seven_compatible?
|
76
|
-
expect(subject.attr_encrypted_encrypted_attributes[:otp_secret][:mode]).to eq(:per_attribute_iv_and_salt)
|
77
|
-
else
|
78
|
-
expect(subject.encrypted_attributes[:otp_secret][:mode]).to eq(:per_attribute_iv_and_salt)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'should be of the mode' do
|
83
|
-
if attr_encrypted_is_rails_seven_compatible?
|
84
|
-
expect(subject.attr_encrypted_encrypted_attributes[:otp_secret][:algorithm]).to eq('aes-256-cbc')
|
85
|
-
else
|
86
|
-
expect(subject.encrypted_attributes[:otp_secret][:algorithm]).to eq('aes-256-cbc')
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def attr_encrypted_is_rails_seven_compatible?
|
91
|
-
Gem::Version.new(AttrEncrypted::Version.string) >= Gem::Version.new('4.0.0')
|
92
|
-
end
|
93
|
-
end
|
94
36
|
end
|
95
37
|
end
|
96
38
|
|
@@ -101,11 +43,11 @@ describe ::Devise::Models::TwoFactorAuthenticatable do
|
|
101
43
|
subject.otp_attempt = 'foo'
|
102
44
|
subject.password_confirmation = 'foo'
|
103
45
|
end
|
104
|
-
it 'otp_attempt should be nill' do
|
46
|
+
it 'otp_attempt should be nill' do
|
105
47
|
subject.clean_up_passwords
|
106
48
|
expect(subject.otp_attempt).to be_nil
|
107
49
|
end
|
108
|
-
it 'password_confirmation should be nill' do
|
50
|
+
it 'password_confirmation should be nill' do
|
109
51
|
subject.clean_up_passwords
|
110
52
|
expect(subject.password_confirmation).to be_nil
|
111
53
|
end
|
@@ -6,12 +6,21 @@ class TwoFactorBackupableDouble
|
|
6
6
|
include ::ActiveModel::Validations::Callbacks
|
7
7
|
extend ::Devise::Models
|
8
8
|
|
9
|
+
# stub out the ::ActiveRecord::Encryption::EncryptableRecord API
|
10
|
+
attr_accessor :otp_secret
|
11
|
+
def self.encrypts(*attrs)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
9
15
|
define_model_callbacks :update
|
10
16
|
|
11
|
-
devise :two_factor_authenticatable, :two_factor_backupable
|
12
|
-
:otp_secret_encryption_key => 'test-key'*4
|
17
|
+
devise :two_factor_authenticatable, :two_factor_backupable
|
13
18
|
|
14
19
|
attr_accessor :otp_backup_codes
|
20
|
+
|
21
|
+
def save!(_)
|
22
|
+
true
|
23
|
+
end
|
15
24
|
end
|
16
25
|
|
17
26
|
describe ::Devise::Models::TwoFactorBackupable do
|
data/spec/spec_helper.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise-two-factor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
7
|
+
- Quinn Wilton
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain:
|
11
11
|
- |
|
@@ -86,7 +86,7 @@ cert_chain:
|
|
86
86
|
vqIDv6JBG9I16h/HhchntKfM58MI1bNZFBSdZqYOJiL8JIjP8HNIk76Y366ppG29
|
87
87
|
EhBYYg==
|
88
88
|
-----END CERTIFICATE-----
|
89
|
-
date:
|
89
|
+
date: 2024-09-17 00:00:00.000000000 Z
|
90
90
|
dependencies:
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: railties
|
@@ -116,32 +116,6 @@ dependencies:
|
|
116
116
|
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: '7.0'
|
119
|
-
- !ruby/object:Gem::Dependency
|
120
|
-
name: attr_encrypted
|
121
|
-
requirement: !ruby/object:Gem::Requirement
|
122
|
-
requirements:
|
123
|
-
- - ">="
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '1.3'
|
126
|
-
- - "!="
|
127
|
-
- !ruby/object:Gem::Version
|
128
|
-
version: '2'
|
129
|
-
- - "<"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '5'
|
132
|
-
type: :runtime
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '1.3'
|
139
|
-
- - "!="
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
version: '2'
|
142
|
-
- - "<"
|
143
|
-
- !ruby/object:Gem::Version
|
144
|
-
version: '5'
|
145
119
|
- !ruby/object:Gem::Dependency
|
146
120
|
name: devise
|
147
121
|
requirement: !ruby/object:Gem::Requirement
|
@@ -240,28 +214,17 @@ dependencies:
|
|
240
214
|
- - ">="
|
241
215
|
- !ruby/object:Gem::Version
|
242
216
|
version: '0'
|
243
|
-
-
|
244
|
-
|
245
|
-
|
246
|
-
requirements:
|
247
|
-
- - ">="
|
248
|
-
- !ruby/object:Gem::Version
|
249
|
-
version: '0'
|
250
|
-
type: :development
|
251
|
-
prerelease: false
|
252
|
-
version_requirements: !ruby/object:Gem::Requirement
|
253
|
-
requirements:
|
254
|
-
- - ">="
|
255
|
-
- !ruby/object:Gem::Version
|
256
|
-
version: '0'
|
257
|
-
description: Barebones two-factor authentication with Devise
|
258
|
-
email: engineers@tinfoilsecurity.com
|
217
|
+
description: Devise-Two-Factor is a minimalist extension to Devise which offers support
|
218
|
+
for two-factor authentication through the TOTP scheme.
|
219
|
+
email:
|
259
220
|
executables: []
|
260
221
|
extensions: []
|
261
222
|
extra_rdoc_files: []
|
262
223
|
files:
|
224
|
+
- ".github/dependabot.yml"
|
263
225
|
- ".github/workflows/ci.yml"
|
264
226
|
- ".gitignore"
|
227
|
+
- ".markdownlint.json"
|
265
228
|
- ".rspec"
|
266
229
|
- Appraisals
|
267
230
|
- CHANGELOG.md
|
@@ -270,18 +233,13 @@ files:
|
|
270
233
|
- LICENSE
|
271
234
|
- README.md
|
272
235
|
- Rakefile
|
236
|
+
- SECURITY.md
|
273
237
|
- UPGRADING.md
|
274
238
|
- certs/tinfoil-cacert.pem
|
275
239
|
- certs/tinfoilsecurity-gems-cert.pem
|
276
240
|
- devise-two-factor.gemspec
|
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
|
284
241
|
- gemfiles/rails_7.0.gemfile
|
242
|
+
- gemfiles/rails_7.1.gemfile
|
285
243
|
- lib/devise-two-factor.rb
|
286
244
|
- lib/devise_two_factor/models.rb
|
287
245
|
- lib/devise_two_factor/models/two_factor_authenticatable.rb
|
@@ -297,11 +255,11 @@ files:
|
|
297
255
|
- spec/devise/models/two_factor_authenticatable_spec.rb
|
298
256
|
- spec/devise/models/two_factor_backupable_spec.rb
|
299
257
|
- spec/spec_helper.rb
|
300
|
-
homepage: https://github.com/
|
258
|
+
homepage: https://github.com/devise-two-factor/devise-two-factor
|
301
259
|
licenses:
|
302
260
|
- MIT
|
303
261
|
metadata: {}
|
304
|
-
post_install_message:
|
262
|
+
post_install_message:
|
305
263
|
rdoc_options: []
|
306
264
|
require_paths:
|
307
265
|
- lib
|
@@ -316,8 +274,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
316
274
|
- !ruby/object:Gem::Version
|
317
275
|
version: '0'
|
318
276
|
requirements: []
|
319
|
-
rubygems_version: 3.
|
320
|
-
signing_key:
|
277
|
+
rubygems_version: 3.5.11
|
278
|
+
signing_key:
|
321
279
|
specification_version: 4
|
322
280
|
summary: Barebones two-factor authentication with Devise
|
323
281
|
test_files:
|
metadata.gz.sig
CHANGED
Binary file
|
data/gemfiles/rails_4.2.gemfile
DELETED
data/gemfiles/rails_5.0.gemfile
DELETED
data/gemfiles/rails_5.1.gemfile
DELETED
data/gemfiles/rails_5.2.gemfile
DELETED
data/gemfiles/rails_6.0.gemfile
DELETED