authlogic 4.1.1 → 4.2.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
- data/CHANGELOG.md +10 -0
- data/UPGRADING.md +4 -2
- data/authlogic.gemspec +2 -2
- data/lib/authlogic.rb +6 -4
- data/lib/authlogic/acts_as_authentic/password.rb +13 -3
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +6 -6
- data/lib/authlogic/crypto_providers.rb +89 -0
- data/lib/authlogic/crypto_providers/aes256.rb +16 -11
- data/lib/authlogic/crypto_providers/md5.rb +2 -1
- data/lib/authlogic/crypto_providers/sha1.rb +8 -7
- data/lib/authlogic/crypto_providers/sha512.rb +0 -21
- data/lib/authlogic/session/callbacks.rb +3 -1
- data/lib/authlogic/session/http_auth.rb +23 -23
- data/lib/authlogic/session/magic_columns.rb +51 -51
- data/lib/authlogic/session/magic_states.rb +22 -22
- data/lib/authlogic/session/params.rb +36 -36
- data/lib/authlogic/session/password.rb +3 -1
- data/lib/authlogic/session/session.rb +34 -34
- data/lib/authlogic/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3081d87618bffbf9f31777254d99aefe983f895699098458ca7583e32935ecef
|
4
|
+
data.tar.gz: 10bdd5b58605ce5c2081a4bc8c9ee206fe5ba679444581446469e03dfde615dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c9afb5dfb70b62983cd5db0c0ae0576c4c956e8c43cc9ff9c4cdb7a803ed0eb8367e84e9978e28ad354cb7f4e443bb54b8b83a3be9fc3edd5f17426627cb9f6
|
7
|
+
data.tar.gz: d56d7d0629606635a73103fdd3da0424c051af48b15a3e4fd6317f7386ba42698cb970e441651bb6febbc098940f113ff4ca417eb0b0506e821bab0b69075e86
|
data/CHANGELOG.md
CHANGED
@@ -14,6 +14,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
14
14
|
* Fixed
|
15
15
|
* None
|
16
16
|
|
17
|
+
## 4.2.0 (2018-07-18)
|
18
|
+
|
19
|
+
* Breaking Changes
|
20
|
+
* None
|
21
|
+
* Added
|
22
|
+
* [#611](https://github.com/binarylogic/authlogic/pull/611) - Deprecate
|
23
|
+
AES256, guide users to choose a better crypto provider
|
24
|
+
* Fixed
|
25
|
+
* None
|
26
|
+
|
17
27
|
## 4.1.1 (2018-05-23)
|
18
28
|
|
19
29
|
* Breaking Changes
|
data/UPGRADING.md
CHANGED
@@ -4,9 +4,11 @@ Supplemental instructions to complement CHANGELOG.md.
|
|
4
4
|
|
5
5
|
## 3.4.0
|
6
6
|
|
7
|
-
In version 3.4.0, the default crypto_provider was changed
|
7
|
+
In version 3.4.0, released 2014-03-03, the default crypto_provider was changed
|
8
|
+
from *Sha512* to *SCrypt*.
|
8
9
|
|
9
|
-
If you never set a crypto_provider and are upgrading, your passwords will break
|
10
|
+
If you never set a crypto_provider and are upgrading, your passwords will break
|
11
|
+
unless you specify `Sha512`.
|
10
12
|
|
11
13
|
``` ruby
|
12
14
|
c.crypto_provider = Authlogic::CryptoProviders::Sha512
|
data/authlogic.gemspec
CHANGED
@@ -27,8 +27,8 @@ require "authlogic/version"
|
|
27
27
|
s.add_dependency "scrypt", ">= 1.2", "< 4.0"
|
28
28
|
s.add_development_dependency "bcrypt", "~> 3.1"
|
29
29
|
s.add_development_dependency "byebug", "~> 10.0"
|
30
|
-
s.add_development_dependency "minitest-reporters", "~> 1.
|
31
|
-
s.add_development_dependency "rubocop", "~> 0.
|
30
|
+
s.add_development_dependency "minitest-reporters", "~> 1.3"
|
31
|
+
s.add_development_dependency "rubocop", "~> 0.58.1"
|
32
32
|
s.add_development_dependency "timecop", "~> 0.7"
|
33
33
|
|
34
34
|
s.files = `git ls-files`.split("\n")
|
data/lib/authlogic.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
# Authlogic uses ActiveSupport's core extensions like `strip_heredoc
|
2
|
-
# ActiveRecord does not `require
|
3
|
-
#
|
4
|
-
#
|
1
|
+
# Authlogic uses ActiveSupport's core extensions like `strip_heredoc` and
|
2
|
+
# `squish`. ActiveRecord does not `require` these exensions, so we must.
|
3
|
+
#
|
4
|
+
# It's possible that we could save a few milliseconds by loading only the
|
5
|
+
# specific core extensions we need, but `all.rb` is simpler. We can revisit this
|
6
|
+
# decision if it becomes a problem.
|
5
7
|
require "active_support/all"
|
6
8
|
|
7
9
|
require "active_record"
|
@@ -195,13 +195,23 @@ module Authlogic
|
|
195
195
|
validates_length_of_password_confirmation_field_options.merge(options)
|
196
196
|
end
|
197
197
|
|
198
|
-
# The class you want to use to encrypt and verify your encrypted
|
199
|
-
# the Authlogic::CryptoProviders module for more info on
|
200
|
-
# how to create your own.
|
198
|
+
# The class you want to use to encrypt and verify your encrypted
|
199
|
+
# passwords. See the Authlogic::CryptoProviders module for more info on
|
200
|
+
# the available methods and how to create your own.
|
201
|
+
#
|
202
|
+
# The family of adaptive hash functions (BCrypt, SCrypt, PBKDF2) is the
|
203
|
+
# best choice for password storage today. We recommend SCrypt. Other
|
204
|
+
# one-way functions like SHA512 are inferior, but widely used.
|
205
|
+
# Reverisbile functions like AES256 are the worst choice.
|
206
|
+
#
|
207
|
+
# You can use the `transition_from_crypto_providers` option to gradually
|
208
|
+
# transition to a better crypto provider without causing your users any
|
209
|
+
# pain.
|
201
210
|
#
|
202
211
|
# * <tt>Default:</tt> CryptoProviders::SCrypt
|
203
212
|
# * <tt>Accepts:</tt> Class
|
204
213
|
def crypto_provider(value = nil)
|
214
|
+
CryptoProviders::Guidance.new(value).impart_wisdom
|
205
215
|
rw_config(:crypto_provider, value, CryptoProviders::SCrypt)
|
206
216
|
end
|
207
217
|
alias_method :crypto_provider=, :crypto_provider
|
@@ -93,13 +93,13 @@ module Authlogic
|
|
93
93
|
module InstanceMethods
|
94
94
|
private
|
95
95
|
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
def act_like_restful_authentication?
|
97
|
+
self.class.act_like_restful_authentication == true
|
98
|
+
end
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
def transition_from_restful_authentication?
|
101
|
+
self.class.transition_from_restful_authentication == true
|
102
|
+
end
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
@@ -1,4 +1,25 @@
|
|
1
1
|
module Authlogic
|
2
|
+
# The acts_as_authentic method has a crypto_provider option. This allows you
|
3
|
+
# to use any type of encryption you like. Just create a class with a class
|
4
|
+
# level encrypt and matches? method. See example below.
|
5
|
+
#
|
6
|
+
# === Example
|
7
|
+
#
|
8
|
+
# class MyAwesomeEncryptionMethod
|
9
|
+
# def self.encrypt(*tokens)
|
10
|
+
# # The tokens passed will be an array of objects, what type of object
|
11
|
+
# # is irrelevant, just do what you need to do with them and return a
|
12
|
+
# # single encrypted string. For example, you will most likely join all
|
13
|
+
# # of the objects into a single string and then encrypt that string.
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# def self.matches?(crypted, *tokens)
|
17
|
+
# # Return true if the crypted string matches the tokens. Depending on
|
18
|
+
# # your algorithm you might decrypt the string then compare it to the
|
19
|
+
# # token, or you might encrypt the tokens and make sure it matches the
|
20
|
+
# # crypted string, its up to you.
|
21
|
+
# end
|
22
|
+
# end
|
2
23
|
module CryptoProviders
|
3
24
|
autoload :MD5, "authlogic/crypto_providers/md5"
|
4
25
|
autoload :Sha1, "authlogic/crypto_providers/sha1"
|
@@ -9,5 +30,73 @@ module Authlogic
|
|
9
30
|
autoload :SCrypt, "authlogic/crypto_providers/scrypt"
|
10
31
|
# crypto_providers/wordpress.rb has never been autoloaded, and now it is
|
11
32
|
# deprecated.
|
33
|
+
|
34
|
+
# Guide users to choose a better crypto provider.
|
35
|
+
class Guidance
|
36
|
+
AES256_DEPRECATED = <<-EOS.strip_heredoc.freeze
|
37
|
+
You have selected AES256 as your authlogic crypto provider. This
|
38
|
+
choice is not suitable for password storage.
|
39
|
+
|
40
|
+
Authlogic will drop its AES256 crypto provider in the next major
|
41
|
+
version. If you're unable to transition away from AES256 please let us
|
42
|
+
know immediately.
|
43
|
+
|
44
|
+
We recommend using a one-way algorithm instead. There are many choices;
|
45
|
+
we recommend scrypt. Use the transition_from_crypto_providers option
|
46
|
+
to make this painless for your users.
|
47
|
+
EOS
|
48
|
+
BUILTIN_PROVIDER_PREFIX = "Authlogic::CryptoProviders::".freeze
|
49
|
+
NONADAPTIVE_ALGORITHM = <<-EOS.strip_heredoc.freeze
|
50
|
+
You have selected %s as your authlogic crypto provider. This algorithm
|
51
|
+
does not have any practical known attacks against it. However, there are
|
52
|
+
better choices.
|
53
|
+
|
54
|
+
Authlogic has no plans yet to deprecate this crypto provider. However,
|
55
|
+
we recommend transitioning to a more secure, adaptive hashing algorithm,
|
56
|
+
like scrypt. Adaptive algorithms are designed to slow down brute force
|
57
|
+
attacks, and over time the iteration count can be increased to make it
|
58
|
+
slower, so it remains resistant to brute-force search attacks even in
|
59
|
+
the face of increasing computation power.
|
60
|
+
|
61
|
+
Use the transition_from_crypto_providers option to make the transition
|
62
|
+
painless for your users.
|
63
|
+
EOS
|
64
|
+
VULNERABLE_ALGORITHM = <<-EOS.strip_heredoc.freeze
|
65
|
+
You have selected %s as your authlogic crypto provider. It is a poor
|
66
|
+
choice because there are known attacks against this algorithm.
|
67
|
+
|
68
|
+
Authlogic has no plans yet to deprecate this crypto provider. However,
|
69
|
+
we recommend transitioning to a secure hashing algorithm. We recommend
|
70
|
+
an adaptive algorithm, like scrypt.
|
71
|
+
|
72
|
+
Use the transition_from_crypto_providers option to make the transition
|
73
|
+
painless for your users.
|
74
|
+
EOS
|
75
|
+
|
76
|
+
def initialize(provider)
|
77
|
+
@provider = provider
|
78
|
+
end
|
79
|
+
|
80
|
+
def impart_wisdom
|
81
|
+
return unless @provider.is_a?(Class)
|
82
|
+
|
83
|
+
# We can only impart wisdom about our own built-in providers.
|
84
|
+
absolute_name = @provider.name
|
85
|
+
return unless absolute_name.start_with?(BUILTIN_PROVIDER_PREFIX)
|
86
|
+
|
87
|
+
# Inspect the string name of the provider, rather than using the
|
88
|
+
# constants in our `when` clauses. If we used the constants, we'd
|
89
|
+
# negate the benefits of the `autoload` above.
|
90
|
+
name = absolute_name.demodulize
|
91
|
+
case name
|
92
|
+
when "AES256"
|
93
|
+
::ActiveSupport::Deprecation.warn(AES256_DEPRECATED)
|
94
|
+
when "MD5", "Sha1"
|
95
|
+
warn(format(VULNERABLE_ALGORITHM, name))
|
96
|
+
when "Sha256", "Sha512"
|
97
|
+
warn(format(NONADAPTIVE_ALGORITHM, name))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
12
101
|
end
|
13
102
|
end
|
@@ -2,21 +2,23 @@ require "openssl"
|
|
2
2
|
|
3
3
|
module Authlogic
|
4
4
|
module CryptoProviders
|
5
|
-
# This encryption method is reversible if you have the supplied key. So in
|
6
|
-
# use this encryption method you must supply it with a key first.
|
7
|
-
# or before your application initializes, you should do
|
5
|
+
# This encryption method is reversible if you have the supplied key. So in
|
6
|
+
# order to use this encryption method you must supply it with a key first.
|
7
|
+
# In an initializer, or before your application initializes, you should do
|
8
|
+
# the following:
|
8
9
|
#
|
9
10
|
# Authlogic::CryptoProviders::AES256.key = "long, unique, and random key"
|
10
11
|
#
|
11
|
-
# My final comment is that this is a strong encryption method, but its main
|
12
|
-
# is that it's reversible. If you do not need to reverse the hash
|
13
|
-
# consider Sha512 or BCrypt instead.
|
12
|
+
# My final comment is that this is a strong encryption method, but its main
|
13
|
+
# weakness is that it's reversible. If you do not need to reverse the hash
|
14
|
+
# then you should consider Sha512 or BCrypt instead.
|
14
15
|
#
|
15
|
-
# Keep your key in a safe place, some even say the key should be stored on a
|
16
|
-
# server. This won't hurt performance because the only time it will
|
17
|
-
# key on the separate server is during initialization,
|
18
|
-
# reasoning behind this is if someone does
|
19
|
-
#
|
16
|
+
# Keep your key in a safe place, some even say the key should be stored on a
|
17
|
+
# separate server. This won't hurt performance because the only time it will
|
18
|
+
# try and access the key on the separate server is during initialization,
|
19
|
+
# which only happens once. The reasoning behind this is if someone does
|
20
|
+
# compromise your server they won't have the key also. Basically, you don't
|
21
|
+
# want to store the key with the lock.
|
20
22
|
class AES256
|
21
23
|
class << self
|
22
24
|
attr_writer :key
|
@@ -53,6 +55,9 @@ module Authlogic
|
|
53
55
|
# (https://github.com/ruby/openssl/commit/5c20a4c014) when openssl
|
54
56
|
# became a gem. Its first release as a gem was 2.0.0, in ruby 2.4.
|
55
57
|
# (See https://github.com/ruby/ruby/blob/v2_4_0/NEWS)
|
58
|
+
#
|
59
|
+
# When we eventually drop support for ruby < 2.4, we can probably also
|
60
|
+
# drop support for openssl gem < 2.
|
56
61
|
def openssl_cipher_class
|
57
62
|
if ::Gem::Version.new(::OpenSSL::VERSION) < ::Gem::Version.new("2.0.0")
|
58
63
|
::OpenSSL::Cipher::Cipher
|
@@ -6,7 +6,8 @@ module Authlogic
|
|
6
6
|
# I highly discourage using this crypto provider as it superbly inferior
|
7
7
|
# to your other options.
|
8
8
|
#
|
9
|
-
# Please use any other provider offered by Authlogic
|
9
|
+
# Please use any other provider offered by Authlogic (except AES256, that
|
10
|
+
# would be even worse).
|
10
11
|
class MD5
|
11
12
|
class << self
|
12
13
|
attr_accessor :join_token
|
@@ -2,9 +2,10 @@ require "digest/sha1"
|
|
2
2
|
|
3
3
|
module Authlogic
|
4
4
|
module CryptoProviders
|
5
|
-
# This class was made for the users transitioning from
|
6
|
-
#
|
7
|
-
# options. Please use any other provider
|
5
|
+
# This class was made for the users transitioning from
|
6
|
+
# restful_authentication. Use of this crypto provider is highly discouraged.
|
7
|
+
# It is far inferior to your other options. Please use any other provider
|
8
|
+
# offered by Authlogic.
|
8
9
|
class Sha1
|
9
10
|
class << self
|
10
11
|
def join_token
|
@@ -12,8 +13,8 @@ module Authlogic
|
|
12
13
|
end
|
13
14
|
attr_writer :join_token
|
14
15
|
|
15
|
-
# The number of times to loop through the encryption. This is ten
|
16
|
-
# what restful_authentication defaults to.
|
16
|
+
# The number of times to loop through the encryption. This is ten
|
17
|
+
# because that is what restful_authentication defaults to.
|
17
18
|
def stretches
|
18
19
|
@stretches ||= 10
|
19
20
|
end
|
@@ -29,8 +30,8 @@ module Authlogic
|
|
29
30
|
digest
|
30
31
|
end
|
31
32
|
|
32
|
-
# Does the crypted password match the tokens? Uses the same tokens that
|
33
|
-
# to encrypt.
|
33
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
34
|
+
# were used to encrypt.
|
34
35
|
def matches?(crypted, *tokens)
|
35
36
|
encrypt(*tokens) == crypted
|
36
37
|
end
|
@@ -1,27 +1,6 @@
|
|
1
1
|
require "digest/sha2"
|
2
2
|
|
3
3
|
module Authlogic
|
4
|
-
# The acts_as_authentic method has a crypto_provider option. This allows you
|
5
|
-
# to use any type of encryption you like. Just create a class with a class
|
6
|
-
# level encrypt and matches? method. See example below.
|
7
|
-
#
|
8
|
-
# === Example
|
9
|
-
#
|
10
|
-
# class MyAwesomeEncryptionMethod
|
11
|
-
# def self.encrypt(*tokens)
|
12
|
-
# # The tokens passed will be an array of objects, what type of object
|
13
|
-
# # is irrelevant, just do what you need to do with them and return a
|
14
|
-
# # single encrypted string. For example, you will most likely join all
|
15
|
-
# # of the objects into a single string and then encrypt that string.
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# def self.matches?(crypted, *tokens)
|
19
|
-
# # Return true if the crypted string matches the tokens. Depending on
|
20
|
-
# # your algorithm you might decrypt the string then compare it to the
|
21
|
-
# # token, or you might encrypt the tokens and make sure it matches the
|
22
|
-
# # crypted string, its up to you.
|
23
|
-
# end
|
24
|
-
# end
|
25
4
|
module CryptoProviders
|
26
5
|
# = Sha512
|
27
6
|
#
|
@@ -133,11 +133,13 @@ module Authlogic
|
|
133
133
|
end
|
134
134
|
|
135
135
|
METHODS.each do |method|
|
136
|
-
class_eval
|
136
|
+
class_eval(
|
137
|
+
<<-EOS, __FILE__, __LINE__ + 1
|
137
138
|
def #{method}
|
138
139
|
run_callbacks(:#{method})
|
139
140
|
end
|
140
141
|
EOS
|
142
|
+
)
|
141
143
|
end
|
142
144
|
|
143
145
|
def save_record(alternate_record = nil)
|
@@ -73,34 +73,34 @@ module Authlogic
|
|
73
73
|
module InstanceMethods
|
74
74
|
private
|
75
75
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
def persist_by_http_auth
|
81
|
-
login_proc = proc do |login, password|
|
82
|
-
if !login.blank? && !password.blank?
|
83
|
-
send("#{login_field}=", login)
|
84
|
-
send("#{password_field}=", password)
|
85
|
-
valid?
|
86
|
-
end
|
87
|
-
end
|
76
|
+
def persist_by_http_auth?
|
77
|
+
allow_http_basic_auth? && login_field && password_field
|
78
|
+
end
|
88
79
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
)
|
94
|
-
|
95
|
-
controller.authenticate_with_http_basic(&login_proc)
|
80
|
+
def persist_by_http_auth
|
81
|
+
login_proc = proc do |login, password|
|
82
|
+
if !login.blank? && !password.blank?
|
83
|
+
send("#{login_field}=", login)
|
84
|
+
send("#{password_field}=", password)
|
85
|
+
valid?
|
96
86
|
end
|
97
|
-
|
98
|
-
false
|
99
87
|
end
|
100
88
|
|
101
|
-
|
102
|
-
|
89
|
+
if self.class.request_http_basic_auth
|
90
|
+
controller.authenticate_or_request_with_http_basic(
|
91
|
+
self.class.http_basic_auth_realm,
|
92
|
+
&login_proc
|
93
|
+
)
|
94
|
+
else
|
95
|
+
controller.authenticate_with_http_basic(&login_proc)
|
103
96
|
end
|
97
|
+
|
98
|
+
false
|
99
|
+
end
|
100
|
+
|
101
|
+
def allow_http_basic_auth?
|
102
|
+
self.class.allow_http_basic_auth == true
|
103
|
+
end
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
@@ -48,71 +48,71 @@ module Authlogic
|
|
48
48
|
module InstanceMethods
|
49
49
|
private
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
51
|
+
def clear_failed_login_count
|
52
|
+
if record.respond_to?(:failed_login_count)
|
53
|
+
record.failed_login_count = 0
|
55
54
|
end
|
55
|
+
end
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
57
|
+
def increase_failed_login_count
|
58
|
+
if invalid_password? && attempted_record.respond_to?(:failed_login_count)
|
59
|
+
attempted_record.failed_login_count ||= 0
|
60
|
+
attempted_record.failed_login_count += 1
|
62
61
|
end
|
62
|
+
end
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
64
|
+
def increment_login_cout
|
65
|
+
if record.respond_to?(:login_count)
|
66
|
+
record.login_count = (record.login_count.blank? ? 1 : record.login_count + 1)
|
68
67
|
end
|
68
|
+
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
70
|
+
def update_info
|
71
|
+
increment_login_cout
|
72
|
+
clear_failed_login_count
|
73
|
+
update_login_timestamps
|
74
|
+
update_login_ip_addresses
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
77
|
+
def update_login_ip_addresses
|
78
|
+
if record.respond_to?(:current_login_ip)
|
79
|
+
record.last_login_ip = record.current_login_ip if record.respond_to?(:last_login_ip)
|
80
|
+
record.current_login_ip = controller.request.ip
|
82
81
|
end
|
82
|
+
end
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
84
|
+
def update_login_timestamps
|
85
|
+
if record.respond_to?(:current_login_at)
|
86
|
+
record.last_login_at = record.current_login_at if record.respond_to?(:last_login_at)
|
87
|
+
record.current_login_at = klass.default_timezone == :utc ? Time.now.utc : Time.now
|
89
88
|
end
|
89
|
+
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
unless controller.last_request_update_allowed?
|
103
|
-
return false
|
104
|
-
end
|
105
|
-
record.last_request_at.blank? ||
|
106
|
-
last_request_at_threshold.to_i.seconds.ago >= record.last_request_at
|
91
|
+
# This method lets authlogic know whether it should allow the
|
92
|
+
# last_request_at field to be updated with the current time.
|
93
|
+
#
|
94
|
+
# See also `last_request_update_allowed?` in
|
95
|
+
# `Authlogic::ControllerAdapters::AbstractAdapter`
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
def set_last_request_at?
|
99
|
+
if !record || !klass.column_names.include?("last_request_at")
|
100
|
+
return false
|
107
101
|
end
|
108
|
-
|
109
|
-
|
110
|
-
record.last_request_at = klass.default_timezone == :utc ? Time.now.utc : Time.now
|
102
|
+
unless controller.last_request_update_allowed?
|
103
|
+
return false
|
111
104
|
end
|
105
|
+
record.last_request_at.blank? ||
|
106
|
+
last_request_at_threshold.to_i.seconds.ago >= record.last_request_at
|
107
|
+
end
|
112
108
|
|
113
|
-
|
114
|
-
|
115
|
-
|
109
|
+
def set_last_request_at
|
110
|
+
record.last_request_at = klass.default_timezone == :utc ? Time.now.utc : Time.now
|
111
|
+
end
|
112
|
+
|
113
|
+
def last_request_at_threshold
|
114
|
+
self.class.last_request_at_threshold
|
115
|
+
end
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
@@ -50,32 +50,32 @@ module Authlogic
|
|
50
50
|
module InstanceMethods
|
51
51
|
private
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
def disable_magic_states?
|
54
|
+
self.class.disable_magic_states == true
|
55
|
+
end
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
# @api private
|
58
|
+
def required_magic_states_for(record)
|
59
|
+
%i[active approved confirmed].select { |state|
|
60
|
+
record.respond_to?("#{state}?")
|
61
|
+
}
|
62
|
+
end
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
)
|
64
|
+
def validate_magic_states
|
65
|
+
return true if attempted_record.nil?
|
66
|
+
required_magic_states_for(attempted_record).each do |required_status|
|
67
|
+
next if attempted_record.send("#{required_status}?")
|
68
|
+
errors.add(
|
69
|
+
:base,
|
70
|
+
I18n.t(
|
71
|
+
"error_messages.not_#{required_status}",
|
72
|
+
default: "Your account is not #{required_status}"
|
74
73
|
)
|
75
|
-
|
76
|
-
|
77
|
-
true
|
74
|
+
)
|
75
|
+
return false
|
78
76
|
end
|
77
|
+
true
|
78
|
+
end
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
@@ -80,50 +80,50 @@ module Authlogic
|
|
80
80
|
module InstanceMethods
|
81
81
|
private
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
83
|
+
def persist_by_params
|
84
|
+
return false unless params_enabled?
|
85
|
+
self.unauthorized_record = search_for_record(
|
86
|
+
"find_by_single_access_token",
|
87
|
+
params_credentials
|
88
|
+
)
|
89
|
+
self.single_access = valid?
|
90
|
+
end
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
if controller.responds_to_single_access_allowed?
|
97
|
-
return controller.single_access_allowed?
|
98
|
-
end
|
99
|
-
params_enabled_by_allowed_request_types?
|
92
|
+
def params_enabled?
|
93
|
+
if !params_credentials || !klass.column_names.include?("single_access_token")
|
94
|
+
return false
|
100
95
|
end
|
101
|
-
|
102
|
-
|
103
|
-
case single_access_allowed_request_types
|
104
|
-
when Array
|
105
|
-
single_access_allowed_request_types.include?(controller.request_content_type) ||
|
106
|
-
single_access_allowed_request_types.include?(:all)
|
107
|
-
else
|
108
|
-
%i[all any].include?(single_access_allowed_request_types)
|
109
|
-
end
|
96
|
+
if controller.responds_to_single_access_allowed?
|
97
|
+
return controller.single_access_allowed?
|
110
98
|
end
|
99
|
+
params_enabled_by_allowed_request_types?
|
100
|
+
end
|
111
101
|
|
112
|
-
|
113
|
-
|
102
|
+
def params_enabled_by_allowed_request_types?
|
103
|
+
case single_access_allowed_request_types
|
104
|
+
when Array
|
105
|
+
single_access_allowed_request_types.include?(controller.request_content_type) ||
|
106
|
+
single_access_allowed_request_types.include?(:all)
|
107
|
+
else
|
108
|
+
%i[all any].include?(single_access_allowed_request_types)
|
114
109
|
end
|
110
|
+
end
|
115
111
|
|
116
|
-
|
117
|
-
|
118
|
-
|
112
|
+
def params_key
|
113
|
+
build_key(self.class.params_key)
|
114
|
+
end
|
119
115
|
|
120
|
-
|
121
|
-
|
122
|
-
|
116
|
+
def single_access?
|
117
|
+
single_access == true
|
118
|
+
end
|
123
119
|
|
124
|
-
|
125
|
-
|
126
|
-
|
120
|
+
def single_access_allowed_request_types
|
121
|
+
self.class.single_access_allowed_request_types
|
122
|
+
end
|
123
|
+
|
124
|
+
def params_credentials
|
125
|
+
controller.params[params_key]
|
126
|
+
end
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
@@ -226,12 +226,14 @@ module Authlogic
|
|
226
226
|
# using form_for don't fill the password with the attempted
|
227
227
|
# password. To prevent this we just create this method that is
|
228
228
|
# private.
|
229
|
-
self.class.class_eval
|
229
|
+
self.class.class_eval(
|
230
|
+
<<-EOS, __FILE__, __LINE__ + 1
|
230
231
|
private
|
231
232
|
def protected_#{password_field}
|
232
233
|
@#{password_field}
|
233
234
|
end
|
234
235
|
EOS
|
236
|
+
)
|
235
237
|
end
|
236
238
|
|
237
239
|
# In keeping with the metaphor of ActiveRecord, verification of the
|
@@ -30,47 +30,47 @@ module Authlogic
|
|
30
30
|
module InstanceMethods
|
31
31
|
private
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
valid?
|
42
|
-
else
|
43
|
-
false
|
33
|
+
# Tries to validate the session from information in the session
|
34
|
+
def persist_by_session
|
35
|
+
persistence_token, record_id = session_credentials
|
36
|
+
if !persistence_token.nil?
|
37
|
+
record = persist_by_session_search(persistence_token, record_id)
|
38
|
+
if record && record.persistence_token == persistence_token
|
39
|
+
self.unauthorized_record = record
|
44
40
|
end
|
41
|
+
valid?
|
42
|
+
else
|
43
|
+
false
|
45
44
|
end
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
47
|
+
# Allow finding by persistence token, because when records are created
|
48
|
+
# the session is maintained in a before_save, when there is no id.
|
49
|
+
# This is done for performance reasons and to save on queries.
|
50
|
+
def persist_by_session_search(persistence_token, record_id)
|
51
|
+
if record_id.nil?
|
52
|
+
search_for_record("find_by_persistence_token", persistence_token.to_s)
|
53
|
+
else
|
54
|
+
search_for_record("find_by_#{klass.primary_key}", record_id.to_s)
|
56
55
|
end
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
def session_credentials
|
59
|
+
[
|
60
|
+
controller.session[session_key],
|
61
|
+
controller.session["#{session_key}_#{klass.primary_key}"]
|
62
|
+
].collect { |i| i.nil? ? i : i.to_s }.compact
|
63
|
+
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
def session_key
|
66
|
+
build_key(self.class.session_key)
|
67
|
+
end
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
69
|
+
def update_session
|
70
|
+
controller.session[session_key] = record && record.persistence_token
|
71
|
+
compound_key = "#{session_key}_#{klass.primary_key}"
|
72
|
+
controller.session[compound_key] = record && record.send(record.class.primary_key)
|
73
|
+
end
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
data/lib/authlogic/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authlogic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Johnson
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-
|
13
|
+
date: 2018-07-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -120,28 +120,28 @@ dependencies:
|
|
120
120
|
requirements:
|
121
121
|
- - "~>"
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version: '1.
|
123
|
+
version: '1.3'
|
124
124
|
type: :development
|
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.
|
130
|
+
version: '1.3'
|
131
131
|
- !ruby/object:Gem::Dependency
|
132
132
|
name: rubocop
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
135
|
- - "~>"
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: 0.
|
137
|
+
version: 0.58.1
|
138
138
|
type: :development
|
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: 0.
|
144
|
+
version: 0.58.1
|
145
145
|
- !ruby/object:Gem::Dependency
|
146
146
|
name: timecop
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|