authlogic 4.5.0 → 6.4.2
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/lib/authlogic/acts_as_authentic/base.rb +19 -19
- data/lib/authlogic/acts_as_authentic/email.rb +3 -170
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +3 -1
- data/lib/authlogic/acts_as_authentic/login.rb +7 -174
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +7 -4
- data/lib/authlogic/acts_as_authentic/password.rb +67 -256
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +8 -5
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -4
- data/lib/authlogic/acts_as_authentic/queries/case_sensitivity.rb +53 -0
- data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +36 -20
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +12 -8
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +10 -8
- data/lib/authlogic/config.rb +9 -1
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +28 -4
- data/lib/authlogic/controller_adapters/rack_adapter.rb +2 -0
- data/lib/authlogic/controller_adapters/rails_adapter.rb +7 -30
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +6 -0
- data/lib/authlogic/cookie_credentials.rb +63 -0
- data/lib/authlogic/crypto_providers/bcrypt.rb +3 -3
- data/lib/authlogic/crypto_providers/md5/v2.rb +35 -0
- data/lib/authlogic/crypto_providers/md5.rb +6 -6
- data/lib/authlogic/crypto_providers/scrypt.rb +2 -0
- data/lib/authlogic/crypto_providers/sha1/v2.rb +41 -0
- data/lib/authlogic/crypto_providers/sha1.rb +7 -6
- data/lib/authlogic/crypto_providers/sha256/v2.rb +58 -0
- data/lib/authlogic/crypto_providers/sha256.rb +5 -0
- data/lib/authlogic/crypto_providers/sha512/v2.rb +39 -0
- data/lib/authlogic/crypto_providers/sha512.rb +9 -5
- data/lib/authlogic/crypto_providers.rb +5 -20
- data/lib/authlogic/errors.rb +50 -0
- data/lib/authlogic/i18n/translator.rb +4 -1
- data/lib/authlogic/i18n.rb +3 -1
- data/lib/authlogic/random.rb +2 -0
- data/lib/authlogic/session/base.rb +2197 -39
- data/lib/authlogic/session/magic_column/assigns_last_request_at.rb +46 -0
- data/lib/authlogic/test_case/mock_api_controller.rb +52 -0
- data/lib/authlogic/test_case/mock_controller.rb +3 -1
- data/lib/authlogic/test_case/mock_cookie_jar.rb +32 -6
- data/lib/authlogic/test_case/mock_logger.rb +2 -0
- data/lib/authlogic/test_case/mock_request.rb +12 -0
- data/lib/authlogic/test_case/rails_request_adapter.rb +9 -1
- data/lib/authlogic/test_case.rb +5 -0
- data/lib/authlogic/version.rb +2 -1
- data/lib/authlogic.rb +5 -28
- metadata +175 -200
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -28
- data/.github/ISSUE_TEMPLATE/feature_proposal.md +0 -32
- data/.github/triage.md +0 -86
- data/.gitignore +0 -15
- data/.rubocop.yml +0 -133
- data/.rubocop_todo.yml +0 -74
- data/.travis.yml +0 -24
- data/CHANGELOG.md +0 -348
- data/CONTRIBUTING.md +0 -91
- data/Gemfile +0 -6
- data/LICENSE +0 -20
- data/README.md +0 -448
- data/Rakefile +0 -21
- data/UPGRADING.md +0 -22
- data/authlogic.gemspec +0 -40
- data/doc/use_normal_rails_validation.md +0 -82
- data/gemfiles/Gemfile.rails-4.2.x +0 -6
- data/gemfiles/Gemfile.rails-5.1.x +0 -6
- data/gemfiles/Gemfile.rails-5.2.x +0 -6
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +0 -106
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +0 -35
- data/lib/authlogic/authenticates_many/association.rb +0 -50
- data/lib/authlogic/authenticates_many/base.rb +0 -81
- data/lib/authlogic/crypto_providers/aes256.rb +0 -71
- data/lib/authlogic/crypto_providers/wordpress.rb +0 -72
- data/lib/authlogic/regex.rb +0 -79
- data/lib/authlogic/session/activation.rb +0 -73
- data/lib/authlogic/session/active_record_trickery.rb +0 -65
- data/lib/authlogic/session/brute_force_protection.rb +0 -127
- data/lib/authlogic/session/callbacks.rb +0 -153
- data/lib/authlogic/session/cookies.rb +0 -329
- data/lib/authlogic/session/existence.rb +0 -103
- data/lib/authlogic/session/foundation.rb +0 -105
- data/lib/authlogic/session/http_auth.rb +0 -107
- data/lib/authlogic/session/id.rb +0 -53
- data/lib/authlogic/session/klass.rb +0 -73
- data/lib/authlogic/session/magic_columns.rb +0 -119
- data/lib/authlogic/session/magic_states.rb +0 -82
- data/lib/authlogic/session/params.rb +0 -130
- data/lib/authlogic/session/password.rb +0 -318
- data/lib/authlogic/session/perishable_token.rb +0 -24
- data/lib/authlogic/session/persistence.rb +0 -77
- data/lib/authlogic/session/priority_record.rb +0 -38
- data/lib/authlogic/session/scopes.rb +0 -138
- data/lib/authlogic/session/session.rb +0 -77
- data/lib/authlogic/session/timeout.rb +0 -103
- data/lib/authlogic/session/unauthorized_record.rb +0 -56
- data/lib/authlogic/session/validation.rb +0 -93
- data/test/acts_as_authentic_test/base_test.rb +0 -27
- data/test/acts_as_authentic_test/email_test.rb +0 -241
- data/test/acts_as_authentic_test/logged_in_status_test.rb +0 -64
- data/test/acts_as_authentic_test/login_test.rb +0 -153
- data/test/acts_as_authentic_test/magic_columns_test.rb +0 -29
- data/test/acts_as_authentic_test/password_test.rb +0 -263
- data/test/acts_as_authentic_test/perishable_token_test.rb +0 -98
- data/test/acts_as_authentic_test/persistence_token_test.rb +0 -62
- data/test/acts_as_authentic_test/restful_authentication_test.rb +0 -48
- data/test/acts_as_authentic_test/session_maintenance_test.rb +0 -150
- data/test/acts_as_authentic_test/single_access_test.rb +0 -46
- data/test/adapter_test.rb +0 -23
- data/test/authenticates_many_test.rb +0 -33
- data/test/config_test.rb +0 -38
- data/test/crypto_provider_test/aes256_test.rb +0 -16
- data/test/crypto_provider_test/bcrypt_test.rb +0 -16
- data/test/crypto_provider_test/scrypt_test.rb +0 -16
- data/test/crypto_provider_test/sha1_test.rb +0 -25
- data/test/crypto_provider_test/sha256_test.rb +0 -16
- data/test/crypto_provider_test/sha512_test.rb +0 -16
- data/test/crypto_provider_test/wordpress_test.rb +0 -26
- data/test/fixtures/companies.yml +0 -5
- data/test/fixtures/employees.yml +0 -17
- data/test/fixtures/projects.yml +0 -3
- data/test/fixtures/users.yml +0 -41
- data/test/i18n/lol.yml +0 -4
- data/test/i18n_test.rb +0 -35
- data/test/libs/affiliate.rb +0 -9
- data/test/libs/company.rb +0 -8
- data/test/libs/employee.rb +0 -9
- data/test/libs/employee_session.rb +0 -4
- data/test/libs/ldaper.rb +0 -5
- data/test/libs/project.rb +0 -5
- data/test/libs/user.rb +0 -9
- data/test/libs/user_session.rb +0 -27
- data/test/random_test.rb +0 -15
- data/test/session_test/activation_test.rb +0 -45
- data/test/session_test/active_record_trickery_test.rb +0 -78
- data/test/session_test/brute_force_protection_test.rb +0 -110
- data/test/session_test/callbacks_test.rb +0 -42
- data/test/session_test/cookies_test.rb +0 -244
- data/test/session_test/credentials_test.rb +0 -0
- data/test/session_test/existence_test.rb +0 -88
- data/test/session_test/foundation_test.rb +0 -24
- data/test/session_test/http_auth_test.rb +0 -60
- data/test/session_test/id_test.rb +0 -19
- data/test/session_test/klass_test.rb +0 -42
- data/test/session_test/magic_columns_test.rb +0 -62
- data/test/session_test/magic_states_test.rb +0 -60
- data/test/session_test/params_test.rb +0 -61
- data/test/session_test/password_test.rb +0 -107
- data/test/session_test/perishability_test.rb +0 -17
- data/test/session_test/persistence_test.rb +0 -35
- data/test/session_test/scopes_test.rb +0 -68
- data/test/session_test/session_test.rb +0 -80
- data/test/session_test/timeout_test.rb +0 -84
- data/test/session_test/unauthorized_record_test.rb +0 -15
- data/test/session_test/validation_test.rb +0 -25
- data/test/test_helper.rb +0 -272
@@ -4,12 +4,25 @@ module Authlogic
|
|
4
4
|
module ActsAsAuthentic
|
5
5
|
module Queries
|
6
6
|
# The query used by public-API method `find_by_smart_case_login_field`.
|
7
|
+
#
|
8
|
+
# We use the rails methods `case_insensitive_comparison` and
|
9
|
+
# `case_sensitive_comparison`. These methods nicely take into account
|
10
|
+
# MySQL collations. (Consider the case where a user *says* they want a
|
11
|
+
# case-sensitive uniqueness validation, but then they configure their
|
12
|
+
# database to have an insensitive collation. Rails will handle this for
|
13
|
+
# us, by downcasing, see
|
14
|
+
# `active_record/connection_adapters/abstract_mysql_adapter.rb`) So that's
|
15
|
+
# great! But, these methods are not part of rails' public API, so there
|
16
|
+
# are no docs. So, everything we know about how to use the methods
|
17
|
+
# correctly comes from mimicing what we find in
|
18
|
+
# `active_record/validations/uniqueness.rb`.
|
19
|
+
#
|
7
20
|
# @api private
|
8
21
|
class FindWithCase
|
9
22
|
# Dup ActiveRecord.gem_version before freezing, in case someone
|
10
23
|
# else wants to modify it. Freezing modifies an object in place.
|
11
24
|
# https://github.com/binarylogic/authlogic/pull/590
|
12
|
-
AR_GEM_VERSION = ActiveRecord.gem_version.dup.freeze
|
25
|
+
AR_GEM_VERSION = ::ActiveRecord.gem_version.dup.freeze
|
13
26
|
|
14
27
|
# @api private
|
15
28
|
def initialize(model_class, field, value, sensitive)
|
@@ -21,44 +34,47 @@ module Authlogic
|
|
21
34
|
|
22
35
|
# @api private
|
23
36
|
def execute
|
24
|
-
|
37
|
+
@model_class.where(comparison).first
|
25
38
|
end
|
26
39
|
|
27
40
|
private
|
28
41
|
|
29
42
|
# @api private
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
@field,
|
34
|
-
@value,
|
35
|
-
ActiveRecord::Type::Value.new
|
36
|
-
)
|
37
|
-
@model_class.where(relation, bind)
|
38
|
-
else
|
39
|
-
@model_class.where(relation)
|
40
|
-
end
|
43
|
+
# @return Arel::Nodes::Equality
|
44
|
+
def comparison
|
45
|
+
@sensitive ? sensitive_comparison : insensitive_comparison
|
41
46
|
end
|
42
47
|
|
43
48
|
# @api private
|
44
|
-
def
|
45
|
-
if
|
49
|
+
def insensitive_comparison
|
50
|
+
if AR_GEM_VERSION > Gem::Version.new("5.3")
|
51
|
+
@model_class.connection.case_insensitive_comparison(
|
52
|
+
@model_class.arel_table[@field], @value
|
53
|
+
)
|
54
|
+
else
|
46
55
|
@model_class.connection.case_insensitive_comparison(
|
47
56
|
@model_class.arel_table,
|
48
57
|
@field,
|
49
58
|
@model_class.columns_hash[@field],
|
50
59
|
@value
|
51
60
|
)
|
52
|
-
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# @api private
|
65
|
+
def sensitive_comparison
|
66
|
+
bound_value = @model_class.predicate_builder.build_bind_attribute(@field, @value)
|
67
|
+
if AR_GEM_VERSION > Gem::Version.new("5.3")
|
68
|
+
@model_class.connection.case_sensitive_comparison(
|
69
|
+
@model_class.arel_table[@field], bound_value
|
70
|
+
)
|
71
|
+
else
|
53
72
|
@model_class.connection.case_sensitive_comparison(
|
54
73
|
@model_class.arel_table,
|
55
74
|
@field,
|
56
75
|
@model_class.columns_hash[@field],
|
57
|
-
|
76
|
+
bound_value
|
58
77
|
)
|
59
|
-
else
|
60
|
-
value = @model_class.connection.case_sensitive_modifier(@value, @field)
|
61
|
-
@model_class.arel_table[@field].eq(value)
|
62
78
|
end
|
63
79
|
end
|
64
80
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Authlogic
|
2
4
|
module ActsAsAuthentic
|
3
5
|
# This is one of my favorite features that I think is pretty cool. It's
|
@@ -40,7 +42,7 @@ module Authlogic
|
|
40
42
|
def log_in_after_create(value = nil)
|
41
43
|
rw_config(:log_in_after_create, value, true)
|
42
44
|
end
|
43
|
-
|
45
|
+
alias log_in_after_create= log_in_after_create
|
44
46
|
|
45
47
|
# In order to turn off automatic maintenance of sessions when updating
|
46
48
|
# the password, just set this to false.
|
@@ -50,7 +52,7 @@ module Authlogic
|
|
50
52
|
def log_in_after_password_change(value = nil)
|
51
53
|
rw_config(:log_in_after_password_change, value, true)
|
52
54
|
end
|
53
|
-
|
55
|
+
alias log_in_after_password_change= log_in_after_password_change
|
54
56
|
|
55
57
|
# As you may know, authlogic sessions can be separate by id (See
|
56
58
|
# Authlogic::Session::Base#id). You can specify here what session ids
|
@@ -62,7 +64,7 @@ module Authlogic
|
|
62
64
|
def session_ids(value = nil)
|
63
65
|
rw_config(:session_ids, value, [nil])
|
64
66
|
end
|
65
|
-
|
67
|
+
alias session_ids= session_ids
|
66
68
|
|
67
69
|
# The name of the associated session class. This is inferred by the name
|
68
70
|
# of the model.
|
@@ -77,7 +79,7 @@ module Authlogic
|
|
77
79
|
end
|
78
80
|
rw_config(:session_class, value, const)
|
79
81
|
end
|
80
|
-
|
82
|
+
alias session_class= session_class
|
81
83
|
end
|
82
84
|
|
83
85
|
# This module, as one of the `acts_as_authentic_modules`, is only included
|
@@ -91,9 +93,9 @@ module Authlogic
|
|
91
93
|
end
|
92
94
|
|
93
95
|
# Save the record and skip session maintenance all together.
|
94
|
-
def save_without_session_maintenance(
|
96
|
+
def save_without_session_maintenance(**options)
|
95
97
|
self.skip_session_maintenance = true
|
96
|
-
result = save(
|
98
|
+
result = save(**options)
|
97
99
|
self.skip_session_maintenance = false
|
98
100
|
result
|
99
101
|
end
|
@@ -114,7 +116,7 @@ module Authlogic
|
|
114
116
|
session_class.activated? &&
|
115
117
|
maintain_session? &&
|
116
118
|
!session_ids.blank? &&
|
117
|
-
|
119
|
+
will_save_change_to_persistence_token?
|
118
120
|
end
|
119
121
|
|
120
122
|
def maintain_session?
|
@@ -174,7 +176,9 @@ module Authlogic
|
|
174
176
|
end
|
175
177
|
|
176
178
|
def log_in_after_password_change?
|
177
|
-
|
179
|
+
persisted? &&
|
180
|
+
will_save_change_to_persistence_token? &&
|
181
|
+
self.class.log_in_after_password_change
|
178
182
|
end
|
179
183
|
end
|
180
184
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Authlogic
|
2
4
|
module ActsAsAuthentic
|
3
|
-
# This module is responsible for maintaining the single_access token. For
|
4
|
-
# information the single access token and how to use it, see
|
5
|
-
#
|
5
|
+
# This module is responsible for maintaining the single_access token. For
|
6
|
+
# more information the single access token and how to use it, see "Params"
|
7
|
+
# in `Session::Base`.
|
6
8
|
module SingleAccessToken
|
7
9
|
def self.included(klass)
|
8
10
|
klass.class_eval do
|
@@ -25,10 +27,7 @@ module Authlogic
|
|
25
27
|
def change_single_access_token_with_password(value = nil)
|
26
28
|
rw_config(:change_single_access_token_with_password, value, false)
|
27
29
|
end
|
28
|
-
|
29
|
-
:change_single_access_token_with_password=,
|
30
|
-
:change_single_access_token_with_password
|
31
|
-
)
|
30
|
+
alias change_single_access_token_with_password= change_single_access_token_with_password
|
32
31
|
end
|
33
32
|
|
34
33
|
# All method, for the single_access token aspect of acts_as_authentic.
|
@@ -41,7 +40,10 @@ module Authlogic
|
|
41
40
|
|
42
41
|
klass.class_eval do
|
43
42
|
include InstanceMethods
|
44
|
-
validates_uniqueness_of :single_access_token,
|
43
|
+
validates_uniqueness_of :single_access_token,
|
44
|
+
case_sensitive: true,
|
45
|
+
if: :will_save_change_to_single_access_token?
|
46
|
+
|
45
47
|
before_validation :reset_single_access_token, if: :reset_single_access_token?
|
46
48
|
if respond_to?(:after_password_set)
|
47
49
|
after_password_set(
|
data/lib/authlogic/config.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Authlogic
|
4
|
+
# Mixed into `Authlogic::ActsAsAuthentic::Base` and
|
5
|
+
# `Authlogic::Session::Base`.
|
2
6
|
module Config
|
3
|
-
E_USE_NORMAL_RAILS_VALIDATION = <<~EOS
|
7
|
+
E_USE_NORMAL_RAILS_VALIDATION = <<~EOS
|
4
8
|
This Authlogic configuration option (%s) is deprecated. Use normal
|
5
9
|
ActiveRecord validation instead. Detailed instructions:
|
6
10
|
https://github.com/binarylogic/authlogic/blob/master/doc/use_normal_rails_validation.md
|
@@ -8,6 +12,10 @@ module Authlogic
|
|
8
12
|
|
9
13
|
def self.extended(klass)
|
10
14
|
klass.class_eval do
|
15
|
+
# TODO: Is this a confusing name, given this module is mixed into
|
16
|
+
# both `Authlogic::ActsAsAuthentic::Base` and
|
17
|
+
# `Authlogic::Session::Base`? Perhaps a more generic name, like
|
18
|
+
# `authlogic_config` would be better?
|
11
19
|
class_attribute :acts_as_authentic_config
|
12
20
|
self.acts_as_authentic_config ||= {}
|
13
21
|
end
|
@@ -1,10 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Authlogic
|
2
4
|
module ControllerAdapters # :nodoc:
|
3
|
-
# Allows you to use Authlogic in any framework you want, not just rails. See
|
4
|
-
# for an example of how to adapt Authlogic to work with
|
5
|
+
# Allows you to use Authlogic in any framework you want, not just rails. See
|
6
|
+
# the RailsAdapter for an example of how to adapt Authlogic to work with
|
7
|
+
# your framework.
|
5
8
|
class AbstractAdapter
|
6
9
|
E_COOKIE_DOMAIN_ADAPTER = "The cookie_domain method has not been " \
|
7
|
-
"implemented by the controller adapter"
|
10
|
+
"implemented by the controller adapter"
|
11
|
+
ENV_SESSION_OPTIONS = "rack.session.options"
|
8
12
|
|
9
13
|
attr_accessor :controller
|
10
14
|
|
@@ -26,7 +30,7 @@ module Authlogic
|
|
26
30
|
end
|
27
31
|
|
28
32
|
def cookie_domain
|
29
|
-
raise NotImplementedError
|
33
|
+
raise NotImplementedError, E_COOKIE_DOMAIN_ADAPTER
|
30
34
|
end
|
31
35
|
|
32
36
|
def params
|
@@ -41,6 +45,26 @@ module Authlogic
|
|
41
45
|
request.content_type
|
42
46
|
end
|
43
47
|
|
48
|
+
# Inform Rack that we would like a new session ID to be assigned. Changes
|
49
|
+
# the ID, but not the contents of the session.
|
50
|
+
#
|
51
|
+
# The `:renew` option is read by `rack/session/abstract/id.rb`.
|
52
|
+
#
|
53
|
+
# This is how Devise (via warden) implements defense against Session
|
54
|
+
# Fixation. Our implementation is copied directly from the warden gem
|
55
|
+
# (set_user in warden/proxy.rb)
|
56
|
+
def renew_session_id
|
57
|
+
env = request.env
|
58
|
+
options = env[ENV_SESSION_OPTIONS]
|
59
|
+
if options
|
60
|
+
if options.frozen?
|
61
|
+
env[ENV_SESSION_OPTIONS] = options.merge(renew: true).freeze
|
62
|
+
else
|
63
|
+
options[:renew] = true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
44
68
|
def session
|
45
69
|
controller.session
|
46
70
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Authlogic
|
4
4
|
module ControllerAdapters
|
@@ -7,8 +7,6 @@ module Authlogic
|
|
7
7
|
# Similar to how ActiveRecord has an adapter for MySQL, PostgreSQL, SQLite,
|
8
8
|
# etc.
|
9
9
|
class RailsAdapter < AbstractAdapter
|
10
|
-
class AuthlogicLoadedTooLateError < StandardError; end
|
11
|
-
|
12
10
|
def authenticate_with_http_basic(&block)
|
13
11
|
controller.authenticate_with_http_basic(&block)
|
14
12
|
end
|
@@ -16,12 +14,11 @@ module Authlogic
|
|
16
14
|
# Returns a `ActionDispatch::Cookies::CookieJar`. See the AC guide
|
17
15
|
# http://guides.rubyonrails.org/action_controller_overview.html#cookies
|
18
16
|
def cookies
|
19
|
-
controller.send(:cookies)
|
17
|
+
controller.respond_to?(:cookies, true) ? controller.send(:cookies) : nil
|
20
18
|
end
|
21
19
|
|
22
20
|
def cookie_domain
|
23
|
-
|
24
|
-
controller.request.session_options[@cookie_domain_key]
|
21
|
+
controller.request.session_options[:domain]
|
25
22
|
end
|
26
23
|
|
27
24
|
def request_content_type
|
@@ -32,26 +29,7 @@ module Authlogic
|
|
32
29
|
# "activates" authlogic.
|
33
30
|
module RailsImplementation
|
34
31
|
def self.included(klass) # :nodoc:
|
35
|
-
|
36
|
-
raise AuthlogicLoadedTooLateError.new(
|
37
|
-
<<~EOS.squish
|
38
|
-
Authlogic is trying to add a callback to ActionController::Base
|
39
|
-
but ApplicationController has already been loaded, so the
|
40
|
-
callback won't be copied into your application. Generally this
|
41
|
-
is due to another gem or plugin requiring your
|
42
|
-
ApplicationController prematurely, such as the
|
43
|
-
resource_controller plugin. Please require Authlogic first,
|
44
|
-
before these other gems / plugins.
|
45
|
-
EOS
|
46
|
-
)
|
47
|
-
end
|
48
|
-
|
49
|
-
# In Rails 4.0.2, the *_filter methods were renamed to *_action.
|
50
|
-
if klass.respond_to? :prepend_before_action
|
51
|
-
klass.prepend_before_action :activate_authlogic
|
52
|
-
else
|
53
|
-
klass.prepend_before_filter :activate_authlogic
|
54
|
-
end
|
32
|
+
klass.prepend_before_action :activate_authlogic
|
55
33
|
end
|
56
34
|
|
57
35
|
private
|
@@ -64,7 +42,6 @@ module Authlogic
|
|
64
42
|
end
|
65
43
|
end
|
66
44
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
)
|
45
|
+
ActiveSupport.on_load(:action_controller) do
|
46
|
+
include Authlogic::ControllerAdapters::RailsAdapter::RailsImplementation
|
47
|
+
end
|
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Authlogic bridge for Sinatra
|
2
4
|
module Authlogic
|
3
5
|
module ControllerAdapters
|
4
6
|
module SinatraAdapter
|
7
|
+
# Cookie management functions
|
5
8
|
class Cookies
|
6
9
|
attr_reader :request, :response
|
7
10
|
|
@@ -23,6 +26,7 @@ module Authlogic
|
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
29
|
+
# Thin wrapper around request and response.
|
26
30
|
class Controller
|
27
31
|
attr_reader :request, :response, :cookies
|
28
32
|
|
@@ -40,11 +44,13 @@ module Authlogic
|
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
47
|
+
# Sinatra controller adapter
|
43
48
|
class Adapter < AbstractAdapter
|
44
49
|
def cookie_domain
|
45
50
|
env["SERVER_NAME"]
|
46
51
|
end
|
47
52
|
|
53
|
+
# Mixed into `Sinatra::Base`
|
48
54
|
module Implementation
|
49
55
|
def self.included(klass)
|
50
56
|
klass.send :before do
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Authlogic
|
4
|
+
# Represents the credentials *in* the cookie. The value of the cookie.
|
5
|
+
# This is primarily a data object. It doesn't interact with controllers.
|
6
|
+
# It doesn't know about eg. cookie expiration.
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class CookieCredentials
|
10
|
+
# @api private
|
11
|
+
class ParseError < RuntimeError
|
12
|
+
end
|
13
|
+
|
14
|
+
DELIMITER = "::"
|
15
|
+
|
16
|
+
attr_reader :persistence_token, :record_id, :remember_me_until
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
# @param persistence_token [String]
|
20
|
+
# @param record_id [String, Numeric]
|
21
|
+
# @param remember_me_until [ActiveSupport::TimeWithZone]
|
22
|
+
def initialize(persistence_token, record_id, remember_me_until)
|
23
|
+
@persistence_token = persistence_token
|
24
|
+
@record_id = record_id
|
25
|
+
@remember_me_until = remember_me_until
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
# @api private
|
30
|
+
def parse(string)
|
31
|
+
parts = string.split(DELIMITER)
|
32
|
+
unless (1..3).cover?(parts.length)
|
33
|
+
raise ParseError, format("Expected 1..3 parts, got %d", parts.length)
|
34
|
+
end
|
35
|
+
new(parts[0], parts[1], parse_time(parts[2]))
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
def parse_time(string)
|
42
|
+
return if string.nil?
|
43
|
+
::Time.parse(string)
|
44
|
+
rescue ::ArgumentError => e
|
45
|
+
raise ParseError, format("Found cookie, cannot parse remember_me_until: #{e}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @api private
|
50
|
+
def remember_me?
|
51
|
+
!@remember_me_until.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
# @api private
|
55
|
+
def to_s
|
56
|
+
[
|
57
|
+
@persistence_token,
|
58
|
+
@record_id.to_s,
|
59
|
+
@remember_me_until&.iso8601
|
60
|
+
].compact.join(DELIMITER)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bcrypt"
|
2
4
|
|
3
5
|
module Authlogic
|
@@ -64,10 +66,8 @@ module Authlogic
|
|
64
66
|
|
65
67
|
def cost=(val)
|
66
68
|
if val < ::BCrypt::Engine::MIN_COST
|
67
|
-
raise ArgumentError
|
68
|
-
"Authlogic's bcrypt cost cannot be set below the engine's " \
|
69
|
+
raise ArgumentError, "Authlogic's bcrypt cost cannot be set below the engine's " \
|
69
70
|
"min cost (#{::BCrypt::Engine::MIN_COST})"
|
70
|
-
)
|
71
71
|
end
|
72
72
|
@cost = val
|
73
73
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/md5"
|
4
|
+
|
5
|
+
module Authlogic
|
6
|
+
module CryptoProviders
|
7
|
+
class MD5
|
8
|
+
# A poor choice. There are known attacks against this algorithm.
|
9
|
+
class V2
|
10
|
+
class << self
|
11
|
+
attr_accessor :join_token
|
12
|
+
|
13
|
+
# The number of times to loop through the encryption.
|
14
|
+
def stretches
|
15
|
+
@stretches ||= 1
|
16
|
+
end
|
17
|
+
attr_writer :stretches
|
18
|
+
|
19
|
+
# Turns your raw password into a MD5 hash.
|
20
|
+
def encrypt(*tokens)
|
21
|
+
digest = tokens.flatten.join(join_token)
|
22
|
+
stretches.times { digest = Digest::MD5.digest(digest) }
|
23
|
+
digest.unpack1("H*")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
27
|
+
# were used to encrypt.
|
28
|
+
def matches?(crypted, *tokens)
|
29
|
+
encrypt(*tokens) == crypted
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "digest/md5"
|
2
4
|
|
3
5
|
module Authlogic
|
4
6
|
module CryptoProviders
|
5
|
-
#
|
6
|
-
# I highly discourage using this crypto provider as it superbly inferior
|
7
|
-
# to your other options.
|
8
|
-
#
|
9
|
-
# Please use any other provider offered by Authlogic (except AES256, that
|
10
|
-
# would be even worse).
|
7
|
+
# A poor choice. There are known attacks against this algorithm.
|
11
8
|
class MD5
|
9
|
+
# V2 hashes the digest bytes in repeated stretches instead of hex characters.
|
10
|
+
autoload :V2, File.join(__dir__, "md5", "v2")
|
11
|
+
|
12
12
|
class << self
|
13
13
|
attr_accessor :join_token
|
14
14
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/sha1"
|
4
|
+
|
5
|
+
module Authlogic
|
6
|
+
module CryptoProviders
|
7
|
+
class Sha1
|
8
|
+
# A poor choice. There are known attacks against this algorithm.
|
9
|
+
class V2
|
10
|
+
class << self
|
11
|
+
def join_token
|
12
|
+
@join_token ||= "--"
|
13
|
+
end
|
14
|
+
attr_writer :join_token
|
15
|
+
|
16
|
+
# The number of times to loop through the encryption.
|
17
|
+
def stretches
|
18
|
+
@stretches ||= 10
|
19
|
+
end
|
20
|
+
attr_writer :stretches
|
21
|
+
|
22
|
+
# Turns your raw password into a Sha1 hash.
|
23
|
+
def encrypt(*tokens)
|
24
|
+
tokens = tokens.flatten
|
25
|
+
digest = tokens.shift
|
26
|
+
stretches.times do
|
27
|
+
digest = Digest::SHA1.digest([digest, *tokens].join(join_token))
|
28
|
+
end
|
29
|
+
digest.unpack1("H*")
|
30
|
+
end
|
31
|
+
|
32
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
33
|
+
# were used to encrypt.
|
34
|
+
def matches?(crypted, *tokens)
|
35
|
+
encrypt(*tokens) == crypted
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,20 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "digest/sha1"
|
2
4
|
|
3
5
|
module Authlogic
|
4
6
|
module CryptoProviders
|
5
|
-
#
|
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.
|
7
|
+
# A poor choice. There are known attacks against this algorithm.
|
9
8
|
class Sha1
|
9
|
+
# V2 hashes the digest bytes in repeated stretches instead of hex characters.
|
10
|
+
autoload :V2, File.join(__dir__, "sha1", "v2")
|
11
|
+
|
10
12
|
class << self
|
11
13
|
def join_token
|
12
14
|
@join_token ||= "--"
|
13
15
|
end
|
14
16
|
attr_writer :join_token
|
15
17
|
|
16
|
-
# The number of times to loop through the encryption.
|
17
|
-
# because that is what restful_authentication defaults to.
|
18
|
+
# The number of times to loop through the encryption.
|
18
19
|
def stretches
|
19
20
|
@stretches ||= 10
|
20
21
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/sha2"
|
4
|
+
|
5
|
+
module Authlogic
|
6
|
+
# The acts_as_authentic method has a crypto_provider option. This allows you
|
7
|
+
# to use any type of encryption you like. Just create a class with a class
|
8
|
+
# level encrypt and matches? method. See example below.
|
9
|
+
#
|
10
|
+
# === Example
|
11
|
+
#
|
12
|
+
# class MyAwesomeEncryptionMethod
|
13
|
+
# def self.encrypt(*tokens)
|
14
|
+
# # the tokens passed will be an array of objects, what type of object
|
15
|
+
# # is irrelevant, just do what you need to do with them and return a
|
16
|
+
# # single encrypted string. for example, you will most likely join all
|
17
|
+
# # of the objects into a single string and then encrypt that string
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def self.matches?(crypted, *tokens)
|
21
|
+
# # return true if the crypted string matches the tokens. Depending on
|
22
|
+
# # your algorithm you might decrypt the string then compare it to the
|
23
|
+
# # token, or you might encrypt the tokens and make sure it matches the
|
24
|
+
# # crypted string, its up to you.
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
module CryptoProviders
|
28
|
+
class Sha256
|
29
|
+
# = Sha256
|
30
|
+
#
|
31
|
+
# Uses the Sha256 hash algorithm to encrypt passwords.
|
32
|
+
class V2
|
33
|
+
class << self
|
34
|
+
attr_accessor :join_token
|
35
|
+
|
36
|
+
# The number of times to loop through the encryption.
|
37
|
+
def stretches
|
38
|
+
@stretches ||= 20
|
39
|
+
end
|
40
|
+
attr_writer :stretches
|
41
|
+
|
42
|
+
# Turns your raw password into a Sha256 hash.
|
43
|
+
def encrypt(*tokens)
|
44
|
+
digest = tokens.flatten.join(join_token)
|
45
|
+
stretches.times { digest = Digest::SHA256.digest(digest) }
|
46
|
+
digest.unpack1("H*")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
50
|
+
# were used to encrypt.
|
51
|
+
def matches?(crypted, *tokens)
|
52
|
+
encrypt(*tokens) == crypted
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "digest/sha2"
|
2
4
|
|
3
5
|
module Authlogic
|
@@ -27,6 +29,9 @@ module Authlogic
|
|
27
29
|
#
|
28
30
|
# Uses the Sha256 hash algorithm to encrypt passwords.
|
29
31
|
class Sha256
|
32
|
+
# V2 hashes the digest bytes in repeated stretches instead of hex characters.
|
33
|
+
autoload :V2, File.join(__dir__, "sha256", "v2")
|
34
|
+
|
30
35
|
class << self
|
31
36
|
attr_accessor :join_token
|
32
37
|
|