authlogic 3.8.0 → 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 +7 -0
- data/lib/authlogic/acts_as_authentic/base.rb +33 -36
- data/lib/authlogic/acts_as_authentic/email.rb +8 -141
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +17 -10
- data/lib/authlogic/acts_as_authentic/login.rb +14 -165
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +13 -10
- data/lib/authlogic/acts_as_authentic/password.rb +186 -254
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +30 -22
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +19 -18
- data/lib/authlogic/acts_as_authentic/queries/case_sensitivity.rb +53 -0
- data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +83 -0
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +94 -62
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +28 -14
- data/lib/authlogic/config.rb +29 -10
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +43 -13
- data/lib/authlogic/controller_adapters/rack_adapter.rb +11 -5
- data/lib/authlogic/controller_adapters/rails_adapter.rb +11 -29
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +8 -2
- data/lib/authlogic/cookie_credentials.rb +63 -0
- data/lib/authlogic/crypto_providers/bcrypt.rb +24 -18
- data/lib/authlogic/crypto_providers/md5/v2.rb +35 -0
- data/lib/authlogic/crypto_providers/md5.rb +8 -6
- data/lib/authlogic/crypto_providers/scrypt.rb +24 -17
- data/lib/authlogic/crypto_providers/sha1/v2.rb +41 -0
- data/lib/authlogic/crypto_providers/sha1.rb +12 -5
- data/lib/authlogic/crypto_providers/sha256/v2.rb +58 -0
- data/lib/authlogic/crypto_providers/sha256.rb +18 -9
- data/lib/authlogic/crypto_providers/sha512/v2.rb +39 -0
- data/lib/authlogic/crypto_providers/sha512.rb +9 -26
- data/lib/authlogic/crypto_providers.rb +77 -1
- data/lib/authlogic/errors.rb +35 -0
- data/lib/authlogic/i18n/translator.rb +4 -1
- data/lib/authlogic/i18n.rb +29 -20
- data/lib/authlogic/random.rb +12 -28
- data/lib/authlogic/session/base.rb +2087 -33
- data/lib/authlogic/session/magic_column/assigns_last_request_at.rb +46 -0
- data/lib/authlogic/test_case/mock_controller.rb +7 -4
- data/lib/authlogic/test_case/mock_cookie_jar.rb +19 -3
- data/lib/authlogic/test_case/mock_logger.rb +2 -0
- data/lib/authlogic/test_case/mock_request.rb +8 -3
- data/lib/authlogic/test_case/rails_request_adapter.rb +5 -2
- data/lib/authlogic/test_case.rb +74 -2
- data/lib/authlogic/version.rb +22 -0
- data/lib/authlogic.rb +33 -54
- metadata +208 -234
- data/.github/ISSUE_TEMPLATE.md +0 -13
- data/.gitignore +0 -14
- data/.rubocop.yml +0 -33
- data/.rubocop_todo.yml +0 -391
- data/.travis.yml +0 -48
- data/CHANGELOG.md +0 -5
- data/CONTRIBUTING.md +0 -60
- data/Gemfile +0 -5
- data/LICENSE +0 -20
- data/README.md +0 -294
- data/Rakefile +0 -21
- data/authlogic.gemspec +0 -27
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +0 -70
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +0 -32
- data/lib/authlogic/authenticates_many/association.rb +0 -50
- data/lib/authlogic/authenticates_many/base.rb +0 -65
- data/lib/authlogic/crypto_providers/aes256.rb +0 -66
- data/lib/authlogic/crypto_providers/wordpress.rb +0 -43
- data/lib/authlogic/regex.rb +0 -48
- data/lib/authlogic/session/activation.rb +0 -70
- data/lib/authlogic/session/active_record_trickery.rb +0 -61
- data/lib/authlogic/session/brute_force_protection.rb +0 -120
- data/lib/authlogic/session/callbacks.rb +0 -105
- data/lib/authlogic/session/cookies.rb +0 -244
- data/lib/authlogic/session/existence.rb +0 -93
- data/lib/authlogic/session/foundation.rb +0 -55
- data/lib/authlogic/session/http_auth.rb +0 -100
- data/lib/authlogic/session/id.rb +0 -48
- data/lib/authlogic/session/klass.rb +0 -70
- data/lib/authlogic/session/magic_columns.rb +0 -116
- data/lib/authlogic/session/magic_states.rb +0 -76
- data/lib/authlogic/session/params.rb +0 -116
- data/lib/authlogic/session/password.rb +0 -308
- data/lib/authlogic/session/perishable_token.rb +0 -23
- data/lib/authlogic/session/persistence.rb +0 -71
- data/lib/authlogic/session/priority_record.rb +0 -35
- data/lib/authlogic/session/scopes.rb +0 -119
- data/lib/authlogic/session/session.rb +0 -67
- data/lib/authlogic/session/timeout.rb +0 -103
- data/lib/authlogic/session/unauthorized_record.rb +0 -51
- data/lib/authlogic/session/validation.rb +0 -93
- data/test/acts_as_authentic_test/base_test.rb +0 -25
- data/test/acts_as_authentic_test/email_test.rb +0 -240
- data/test/acts_as_authentic_test/logged_in_status_test.rb +0 -62
- data/test/acts_as_authentic_test/login_test.rb +0 -156
- data/test/acts_as_authentic_test/magic_columns_test.rb +0 -27
- data/test/acts_as_authentic_test/password_test.rb +0 -249
- data/test/acts_as_authentic_test/perishable_token_test.rb +0 -90
- data/test/acts_as_authentic_test/persistence_token_test.rb +0 -56
- data/test/acts_as_authentic_test/restful_authentication_test.rb +0 -37
- data/test/acts_as_authentic_test/session_maintenance_test.rb +0 -96
- data/test/acts_as_authentic_test/single_access_test.rb +0 -44
- data/test/authenticates_many_test.rb +0 -31
- data/test/config_test.rb +0 -36
- data/test/crypto_provider_test/aes256_test.rb +0 -14
- data/test/crypto_provider_test/bcrypt_test.rb +0 -14
- data/test/crypto_provider_test/scrypt_test.rb +0 -14
- data/test/crypto_provider_test/sha1_test.rb +0 -23
- data/test/crypto_provider_test/sha256_test.rb +0 -14
- data/test/crypto_provider_test/sha512_test.rb +0 -14
- 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/gemfiles/Gemfile.rails-3.2.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.0.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.1.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.2.x +0 -7
- data/test/gemfiles/Gemfile.rails-5.0.x +0 -6
- data/test/gemfiles/Gemfile.rails-5.1.x +0 -6
- data/test/gemfiles/Gemfile.rails-5.2.x +0 -6
- data/test/i18n/lol.yml +0 -4
- data/test/i18n_test.rb +0 -33
- data/test/libs/affiliate.rb +0 -7
- data/test/libs/company.rb +0 -6
- data/test/libs/employee.rb +0 -7
- data/test/libs/employee_session.rb +0 -2
- data/test/libs/ldaper.rb +0 -3
- data/test/libs/project.rb +0 -3
- data/test/libs/user.rb +0 -7
- data/test/libs/user_session.rb +0 -25
- data/test/random_test.rb +0 -43
- data/test/session_test/activation_test.rb +0 -43
- data/test/session_test/active_record_trickery_test.rb +0 -75
- data/test/session_test/brute_force_protection_test.rb +0 -108
- data/test/session_test/callbacks_test.rb +0 -34
- data/test/session_test/cookies_test.rb +0 -201
- data/test/session_test/credentials_test.rb +0 -0
- data/test/session_test/existence_test.rb +0 -75
- data/test/session_test/foundation_test.rb +0 -6
- data/test/session_test/http_auth_test.rb +0 -56
- data/test/session_test/id_test.rb +0 -17
- data/test/session_test/klass_test.rb +0 -40
- data/test/session_test/magic_columns_test.rb +0 -62
- data/test/session_test/magic_states_test.rb +0 -58
- data/test/session_test/params_test.rb +0 -53
- data/test/session_test/password_test.rb +0 -105
- data/test/session_test/perishability_test.rb +0 -15
- data/test/session_test/persistence_test.rb +0 -32
- data/test/session_test/scopes_test.rb +0 -60
- data/test/session_test/session_test.rb +0 -78
- data/test/session_test/timeout_test.rb +0 -82
- data/test/session_test/unauthorized_record_test.rb +0 -13
- data/test/session_test/validation_test.rb +0 -23
- data/test/test_helper.rb +0 -233
@@ -1,18 +1,24 @@
|
|
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
|
9
|
+
E_COOKIE_DOMAIN_ADAPTER = "The cookie_domain method has not been " \
|
10
|
+
"implemented by the controller adapter"
|
11
|
+
|
6
12
|
attr_accessor :controller
|
7
13
|
|
8
14
|
def initialize(controller)
|
9
15
|
self.controller = controller
|
10
16
|
end
|
11
17
|
|
12
|
-
def authenticate_with_http_basic
|
18
|
+
def authenticate_with_http_basic
|
13
19
|
@auth = Rack::Auth::Basic::Request.new(controller.request.env)
|
14
|
-
if @auth.provided?
|
15
|
-
|
20
|
+
if @auth.provided? && @auth.basic?
|
21
|
+
yield(*@auth.credentials)
|
16
22
|
else
|
17
23
|
false
|
18
24
|
end
|
@@ -23,7 +29,7 @@ module Authlogic
|
|
23
29
|
end
|
24
30
|
|
25
31
|
def cookie_domain
|
26
|
-
raise NotImplementedError
|
32
|
+
raise NotImplementedError, E_COOKIE_DOMAIN_ADAPTER
|
27
33
|
end
|
28
34
|
|
29
35
|
def params
|
@@ -50,19 +56,43 @@ module Authlogic
|
|
50
56
|
controller.send(:single_access_allowed?)
|
51
57
|
end
|
52
58
|
|
53
|
-
|
54
|
-
|
59
|
+
# You can disable the updating of `last_request_at`
|
60
|
+
# on a per-controller basis.
|
61
|
+
#
|
62
|
+
# # in your controller
|
63
|
+
# def last_request_update_allowed?
|
64
|
+
# false
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# For example, what if you had a javascript function that polled the
|
68
|
+
# server updating how much time is left in their session before it
|
69
|
+
# times out. Obviously you would want to ignore this request, because
|
70
|
+
# then the user would never time out. So you can do something like
|
71
|
+
# this in your controller:
|
72
|
+
#
|
73
|
+
# def last_request_update_allowed?
|
74
|
+
# action_name != "update_session_time_left"
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# See `authlogic/session/magic_columns.rb` to learn more about the
|
78
|
+
# `last_request_at` column itself.
|
79
|
+
def last_request_update_allowed?
|
80
|
+
if controller.respond_to?(:last_request_update_allowed?, true)
|
81
|
+
controller.send(:last_request_update_allowed?)
|
82
|
+
else
|
83
|
+
true
|
84
|
+
end
|
55
85
|
end
|
56
86
|
|
57
|
-
def
|
58
|
-
controller.
|
87
|
+
def respond_to_missing?(*args)
|
88
|
+
super(*args) || controller.respond_to?(*args)
|
59
89
|
end
|
60
90
|
|
61
91
|
private
|
62
92
|
|
63
|
-
|
64
|
-
|
65
|
-
|
93
|
+
def method_missing(id, *args, &block)
|
94
|
+
controller.send(id, *args, &block)
|
95
|
+
end
|
66
96
|
end
|
67
97
|
end
|
68
98
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Authlogic
|
2
4
|
module ControllerAdapters
|
3
5
|
# Adapter for authlogic to make it function as a Rack middleware.
|
@@ -32,7 +34,7 @@ module Authlogic
|
|
32
34
|
# # Authlogic options go here
|
33
35
|
# end
|
34
36
|
#
|
35
|
-
# class User <
|
37
|
+
# class User < ApplicationRecord
|
36
38
|
# acts_as_authentic
|
37
39
|
# end
|
38
40
|
#
|
@@ -48,7 +50,7 @@ module Authlogic
|
|
48
50
|
end
|
49
51
|
|
50
52
|
def remote_ip
|
51
|
-
|
53
|
+
ip
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
@@ -56,10 +58,14 @@ module Authlogic
|
|
56
58
|
Authlogic::Session::Base.controller = self
|
57
59
|
end
|
58
60
|
|
59
|
-
# Rack Requests stores cookies with not just the value, but also with
|
60
|
-
#
|
61
|
+
# Rack Requests stores cookies with not just the value, but also with
|
62
|
+
# flags and expire information in the hash. Authlogic does not like this,
|
63
|
+
# so we drop everything except the cookie value.
|
61
64
|
def cookies
|
62
|
-
controller
|
65
|
+
controller
|
66
|
+
.cookies
|
67
|
+
.map { |key, value_hash| { key => value_hash[:value] } }
|
68
|
+
.inject(:merge) || {}
|
63
69
|
end
|
64
70
|
end
|
65
71
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Authlogic
|
4
4
|
module ControllerAdapters
|
@@ -7,19 +7,18 @@ 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
|
15
13
|
|
14
|
+
# Returns a `ActionDispatch::Cookies::CookieJar`. See the AC guide
|
15
|
+
# http://guides.rubyonrails.org/action_controller_overview.html#cookies
|
16
16
|
def cookies
|
17
17
|
controller.send(:cookies)
|
18
18
|
end
|
19
19
|
|
20
20
|
def cookie_domain
|
21
|
-
|
22
|
-
controller.request.session_options[@cookie_domain_key]
|
21
|
+
controller.request.session_options[:domain]
|
23
22
|
end
|
24
23
|
|
25
24
|
def request_content_type
|
@@ -30,36 +29,19 @@ module Authlogic
|
|
30
29
|
# "activates" authlogic.
|
31
30
|
module RailsImplementation
|
32
31
|
def self.included(klass) # :nodoc:
|
33
|
-
|
34
|
-
raise AuthlogicLoadedTooLateError.new(
|
35
|
-
<<-EOS.strip_heredoc
|
36
|
-
Authlogic is trying to add a callback to ActionController::Base
|
37
|
-
but ApplicationController has already been loaded, so the
|
38
|
-
callback won't be copied into your application. Generally this
|
39
|
-
is due to another gem or plugin requiring your
|
40
|
-
ApplicationController prematurely, such as the
|
41
|
-
resource_controller plugin. Please require Authlogic first,
|
42
|
-
before these other gems / plugins.
|
43
|
-
EOS
|
44
|
-
)
|
45
|
-
end
|
46
|
-
|
47
|
-
# In Rails 4.0.2, the *_filter methods were renamed to *_action.
|
48
|
-
if klass.respond_to? :prepend_before_action
|
49
|
-
klass.prepend_before_action :activate_authlogic
|
50
|
-
else
|
51
|
-
klass.prepend_before_filter :activate_authlogic
|
52
|
-
end
|
32
|
+
klass.prepend_before_action :activate_authlogic
|
53
33
|
end
|
54
34
|
|
55
35
|
private
|
56
36
|
|
57
|
-
|
58
|
-
|
59
|
-
|
37
|
+
def activate_authlogic
|
38
|
+
Authlogic::Session::Base.controller = RailsAdapter.new(self)
|
39
|
+
end
|
60
40
|
end
|
61
41
|
end
|
62
42
|
end
|
63
43
|
end
|
64
44
|
|
65
|
-
|
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
|
|
@@ -32,7 +36,7 @@ module Authlogic
|
|
32
36
|
end
|
33
37
|
|
34
38
|
def session
|
35
|
-
env[
|
39
|
+
env["rack.session"]
|
36
40
|
end
|
37
41
|
|
38
42
|
def method_missing(meth, *args, &block)
|
@@ -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
|
-
env[
|
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
|
@@ -16,10 +18,18 @@ module Authlogic
|
|
16
18
|
# require "benchmark"
|
17
19
|
#
|
18
20
|
# Benchmark.bm(18) do |x|
|
19
|
-
# x.report("BCrypt (cost = 10:") {
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# x.report("
|
21
|
+
# x.report("BCrypt (cost = 10:") {
|
22
|
+
# 100.times { BCrypt::Password.create("mypass", :cost => 10) }
|
23
|
+
# }
|
24
|
+
# x.report("BCrypt (cost = 4:") {
|
25
|
+
# 100.times { BCrypt::Password.create("mypass", :cost => 4) }
|
26
|
+
# }
|
27
|
+
# x.report("Sha512:") {
|
28
|
+
# 100.times { Digest::SHA512.hexdigest("mypass") }
|
29
|
+
# }
|
30
|
+
# x.report("Sha1:") {
|
31
|
+
# 100.times { Digest::SHA1.hexdigest("mypass") }
|
32
|
+
# }
|
23
33
|
# end
|
24
34
|
#
|
25
35
|
# user system total real
|
@@ -56,17 +66,15 @@ module Authlogic
|
|
56
66
|
|
57
67
|
def cost=(val)
|
58
68
|
if val < ::BCrypt::Engine::MIN_COST
|
59
|
-
raise ArgumentError
|
60
|
-
"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 " \
|
61
70
|
"min cost (#{::BCrypt::Engine::MIN_COST})"
|
62
|
-
)
|
63
71
|
end
|
64
72
|
@cost = val
|
65
73
|
end
|
66
74
|
|
67
75
|
# Creates a BCrypt hash for the password passed.
|
68
76
|
def encrypt(*tokens)
|
69
|
-
::BCrypt::Password.create(join_tokens(tokens), :
|
77
|
+
::BCrypt::Password.create(join_tokens(tokens), cost: cost)
|
70
78
|
end
|
71
79
|
|
72
80
|
# Does the hash match the tokens? Uses the same tokens that were used to
|
@@ -90,17 +98,15 @@ module Authlogic
|
|
90
98
|
|
91
99
|
private
|
92
100
|
|
93
|
-
|
94
|
-
|
95
|
-
|
101
|
+
def join_tokens(tokens)
|
102
|
+
tokens.flatten.join
|
103
|
+
end
|
96
104
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
103
|
-
end
|
105
|
+
def new_from_hash(hash)
|
106
|
+
::BCrypt::Password.new(hash)
|
107
|
+
rescue ::BCrypt::Errors::InvalidHash
|
108
|
+
nil
|
109
|
+
end
|
104
110
|
end
|
105
111
|
end
|
106
112
|
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.unpack("H*")[0]
|
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,13 +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.
|
7
|
+
# A poor choice. There are known attacks against this algorithm.
|
10
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
|
+
|
11
12
|
class << self
|
12
13
|
attr_accessor :join_token
|
13
14
|
|
@@ -24,7 +25,8 @@ module Authlogic
|
|
24
25
|
digest
|
25
26
|
end
|
26
27
|
|
27
|
-
# Does the crypted password match the tokens? Uses the same tokens that
|
28
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
29
|
+
# were used to encrypt.
|
28
30
|
def matches?(crypted, *tokens)
|
29
31
|
encrypt(*tokens) == crypted
|
30
32
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "scrypt"
|
2
4
|
|
3
5
|
module Authlogic
|
@@ -19,7 +21,13 @@ module Authlogic
|
|
19
21
|
# end
|
20
22
|
class SCrypt
|
21
23
|
class << self
|
22
|
-
DEFAULTS = {
|
24
|
+
DEFAULTS = {
|
25
|
+
key_len: 32,
|
26
|
+
salt_size: 8,
|
27
|
+
max_time: 0.2,
|
28
|
+
max_mem: 1024 * 1024,
|
29
|
+
max_memfrac: 0.5
|
30
|
+
}.freeze
|
23
31
|
|
24
32
|
attr_writer :key_len, :salt_size, :max_time, :max_mem, :max_memfrac
|
25
33
|
# Key length - length in bytes of generated key, from 16 to 512.
|
@@ -42,7 +50,8 @@ module Authlogic
|
|
42
50
|
@max_mem ||= DEFAULTS[:max_mem]
|
43
51
|
end
|
44
52
|
|
45
|
-
# Max memory fraction - maximum memory out of all available. Always
|
53
|
+
# Max memory fraction - maximum memory out of all available. Always
|
54
|
+
# greater than zero and <= 0.5.
|
46
55
|
def max_memfrac
|
47
56
|
@max_memfrac ||= DEFAULTS[:max_memfrac]
|
48
57
|
end
|
@@ -51,11 +60,11 @@ module Authlogic
|
|
51
60
|
def encrypt(*tokens)
|
52
61
|
::SCrypt::Password.create(
|
53
62
|
join_tokens(tokens),
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
58
|
-
:
|
63
|
+
key_len: key_len,
|
64
|
+
salt_size: salt_size,
|
65
|
+
max_mem: max_mem,
|
66
|
+
max_memfrac: max_memfrac,
|
67
|
+
max_time: max_time
|
59
68
|
)
|
60
69
|
end
|
61
70
|
|
@@ -68,17 +77,15 @@ module Authlogic
|
|
68
77
|
|
69
78
|
private
|
70
79
|
|
71
|
-
|
72
|
-
|
73
|
-
|
80
|
+
def join_tokens(tokens)
|
81
|
+
tokens.flatten.join
|
82
|
+
end
|
74
83
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
84
|
+
def new_from_hash(hash)
|
85
|
+
::SCrypt::Password.new(hash)
|
86
|
+
rescue ::SCrypt::Errors::InvalidHash
|
87
|
+
nil
|
88
|
+
end
|
82
89
|
end
|
83
90
|
end
|
84
91
|
end
|
@@ -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.unpack("H*")[0]
|
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,17 +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
|
-
# crypto provider as it is far inferior to your other options. Please use any other provider offered by Authlogic.
|
7
|
+
# A poor choice. There are known attacks against this algorithm.
|
7
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
|
+
|
8
12
|
class << self
|
9
13
|
def join_token
|
10
14
|
@join_token ||= "--"
|
11
15
|
end
|
12
16
|
attr_writer :join_token
|
13
17
|
|
14
|
-
# The number of times to loop through the encryption.
|
18
|
+
# The number of times to loop through the encryption.
|
15
19
|
def stretches
|
16
20
|
@stretches ||= 10
|
17
21
|
end
|
@@ -21,11 +25,14 @@ module Authlogic
|
|
21
25
|
def encrypt(*tokens)
|
22
26
|
tokens = tokens.flatten
|
23
27
|
digest = tokens.shift
|
24
|
-
stretches.times
|
28
|
+
stretches.times do
|
29
|
+
digest = Digest::SHA1.hexdigest([digest, *tokens].join(join_token))
|
30
|
+
end
|
25
31
|
digest
|
26
32
|
end
|
27
33
|
|
28
|
-
# Does the crypted password match the tokens? Uses the same tokens that
|
34
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
35
|
+
# were used to encrypt.
|
29
36
|
def matches?(crypted, *tokens)
|
30
37
|
encrypt(*tokens) == crypted
|
31
38
|
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.unpack("H*")[0]
|
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
|