cb-sorcery 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +56 -0
- data/.rspec +1 -0
- data/.travis.yml +40 -0
- data/CHANGELOG.md +263 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +20 -0
- data/README.md +360 -0
- data/Rakefile +6 -0
- data/gemfiles/active_record-rails40.gemfile +7 -0
- data/gemfiles/active_record-rails41.gemfile +7 -0
- data/lib/generators/sorcery/USAGE +22 -0
- data/lib/generators/sorcery/helpers.rb +40 -0
- data/lib/generators/sorcery/install_generator.rb +95 -0
- data/lib/generators/sorcery/templates/initializer.rb +451 -0
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +10 -0
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +9 -0
- data/lib/generators/sorcery/templates/migration/core.rb +13 -0
- data/lib/generators/sorcery/templates/migration/external.rb +12 -0
- data/lib/generators/sorcery/templates/migration/remember_me.rb +8 -0
- data/lib/generators/sorcery/templates/migration/reset_password.rb +9 -0
- data/lib/generators/sorcery/templates/migration/user_activation.rb +9 -0
- data/lib/sorcery.rb +85 -0
- data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
- data/lib/sorcery/adapters/base_adapter.rb +30 -0
- data/lib/sorcery/controller.rb +157 -0
- data/lib/sorcery/controller/config.rb +65 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +82 -0
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +38 -0
- data/lib/sorcery/controller/submodules/external.rb +199 -0
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +74 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +81 -0
- data/lib/sorcery/controller/submodules/session_timeout.rb +56 -0
- data/lib/sorcery/crypto_providers/aes256.rb +51 -0
- data/lib/sorcery/crypto_providers/bcrypt.rb +97 -0
- data/lib/sorcery/crypto_providers/common.rb +35 -0
- data/lib/sorcery/crypto_providers/md5.rb +19 -0
- data/lib/sorcery/crypto_providers/sha1.rb +28 -0
- data/lib/sorcery/crypto_providers/sha256.rb +36 -0
- data/lib/sorcery/crypto_providers/sha512.rb +36 -0
- data/lib/sorcery/engine.rb +21 -0
- data/lib/sorcery/model.rb +183 -0
- data/lib/sorcery/model/config.rb +96 -0
- data/lib/sorcery/model/submodules/activity_logging.rb +70 -0
- data/lib/sorcery/model/submodules/brute_force_protection.rb +125 -0
- data/lib/sorcery/model/submodules/external.rb +100 -0
- data/lib/sorcery/model/submodules/remember_me.rb +62 -0
- data/lib/sorcery/model/submodules/reset_password.rb +131 -0
- data/lib/sorcery/model/submodules/user_activation.rb +149 -0
- data/lib/sorcery/model/temporary_token.rb +30 -0
- data/lib/sorcery/protocols/certs/ca-bundle.crt +5182 -0
- data/lib/sorcery/protocols/oauth.rb +42 -0
- data/lib/sorcery/protocols/oauth2.rb +47 -0
- data/lib/sorcery/providers/base.rb +27 -0
- data/lib/sorcery/providers/facebook.rb +63 -0
- data/lib/sorcery/providers/github.rb +51 -0
- data/lib/sorcery/providers/google.rb +51 -0
- data/lib/sorcery/providers/jira.rb +77 -0
- data/lib/sorcery/providers/linkedin.rb +66 -0
- data/lib/sorcery/providers/liveid.rb +53 -0
- data/lib/sorcery/providers/twitter.rb +59 -0
- data/lib/sorcery/providers/vk.rb +63 -0
- data/lib/sorcery/providers/xing.rb +64 -0
- data/lib/sorcery/railties/tasks.rake +6 -0
- data/lib/sorcery/test_helpers/internal.rb +78 -0
- data/lib/sorcery/test_helpers/internal/rails.rb +68 -0
- data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
- data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
- data/lib/sorcery/version.rb +3 -0
- data/sorcery.gemspec +34 -0
- data/spec/active_record/user_activation_spec.rb +18 -0
- data/spec/active_record/user_activity_logging_spec.rb +17 -0
- data/spec/active_record/user_brute_force_protection_spec.rb +16 -0
- data/spec/active_record/user_oauth_spec.rb +16 -0
- data/spec/active_record/user_remember_me_spec.rb +16 -0
- data/spec/active_record/user_reset_password_spec.rb +16 -0
- data/spec/active_record/user_spec.rb +37 -0
- data/spec/controllers/controller_activity_logging_spec.rb +124 -0
- data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
- data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
- data/spec/controllers/controller_oauth2_spec.rb +407 -0
- data/spec/controllers/controller_oauth_spec.rb +240 -0
- data/spec/controllers/controller_remember_me_spec.rb +117 -0
- data/spec/controllers/controller_session_timeout_spec.rb +80 -0
- data/spec/controllers/controller_spec.rb +215 -0
- data/spec/orm/active_record.rb +21 -0
- data/spec/rails_app/app/active_record/authentication.rb +3 -0
- data/spec/rails_app/app/active_record/user.rb +5 -0
- data/spec/rails_app/app/active_record/user_provider.rb +3 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +265 -0
- data/spec/rails_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_app/app/mailers/sorcery_mailer.rb +32 -0
- data/spec/rails_app/app/views/application/index.html.erb +17 -0
- data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_email.html.erb +17 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_email.text.erb +9 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_needed_email.html.erb +17 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
- data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
- data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
- data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
- data/spec/rails_app/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -0
- data/spec/rails_app/config.ru +4 -0
- data/spec/rails_app/config/application.rb +56 -0
- data/spec/rails_app/config/boot.rb +4 -0
- data/spec/rails_app/config/database.yml +22 -0
- data/spec/rails_app/config/environment.rb +5 -0
- data/spec/rails_app/config/environments/test.rb +37 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/inflections.rb +10 -0
- data/spec/rails_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails_app/config/initializers/secret_token.rb +7 -0
- data/spec/rails_app/config/initializers/session_store.rb +12 -0
- data/spec/rails_app/config/locales/en.yml +5 -0
- data/spec/rails_app/config/routes.rb +48 -0
- data/spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
- data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +19 -0
- data/spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +13 -0
- data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +16 -0
- data/spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb +22 -0
- data/spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
- data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
- data/spec/rails_app/db/schema.rb +23 -0
- data/spec/rails_app/db/seeds.rb +7 -0
- data/spec/shared_examples/user_activation_shared_examples.rb +242 -0
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +97 -0
- data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +156 -0
- data/spec/shared_examples/user_oauth_shared_examples.rb +36 -0
- data/spec/shared_examples/user_remember_me_shared_examples.rb +57 -0
- data/spec/shared_examples/user_reset_password_shared_examples.rb +263 -0
- data/spec/shared_examples/user_shared_examples.rb +467 -0
- data/spec/sorcery_crypto_providers_spec.rb +198 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +41 -0
- metadata +350 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Controller
|
3
|
+
module Submodules
|
4
|
+
# The Remember Me submodule takes care of setting the user's cookie so that he will
|
5
|
+
# be automatically logged in to the site on every visit,
|
6
|
+
# until the cookie expires.
|
7
|
+
# See Sorcery::Model::Submodules::RememberMe for configuration options.
|
8
|
+
module RememberMe
|
9
|
+
def self.included(base)
|
10
|
+
base.send(:include, InstanceMethods)
|
11
|
+
Config.module_eval do
|
12
|
+
class << self
|
13
|
+
attr_accessor :remember_me_httponly
|
14
|
+
def merge_remember_me_defaults!
|
15
|
+
@defaults.merge!(:@remember_me_httponly => true)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
merge_remember_me_defaults!
|
19
|
+
end
|
20
|
+
Config.login_sources << :login_from_cookie
|
21
|
+
Config.after_login << :remember_me_if_asked_to
|
22
|
+
Config.after_logout << :forget_me!
|
23
|
+
end
|
24
|
+
|
25
|
+
module InstanceMethods
|
26
|
+
# This method sets the cookie and calls the user to save the token and the expiration to db.
|
27
|
+
def remember_me!
|
28
|
+
current_user.remember_me!
|
29
|
+
set_remember_me_cookie!(current_user)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Clears the cookie and clears the token from the db.
|
33
|
+
def forget_me!
|
34
|
+
current_user.forget_me!
|
35
|
+
cookies.delete(:remember_me_token, :domain => Config.cookie_domain)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Override.
|
39
|
+
# logins a user instance, and optionally remembers him.
|
40
|
+
def auto_login(user, should_remember = false)
|
41
|
+
session[:user_id] = user.id.to_s
|
42
|
+
@current_user = user
|
43
|
+
remember_me! if should_remember
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
# calls remember_me! if a third credential was passed to the login method.
|
49
|
+
# Runs as a hook after login.
|
50
|
+
def remember_me_if_asked_to(user, credentials)
|
51
|
+
remember_me! if ( credentials.size == 3 && credentials[2] && credentials[2] != "0" )
|
52
|
+
end
|
53
|
+
|
54
|
+
# Checks the cookie for a remember me token, tried to find a user with that token
|
55
|
+
# and logs the user in if found.
|
56
|
+
# Runs as a login source. See 'current_user' method for how it is used.
|
57
|
+
def login_from_cookie
|
58
|
+
user = cookies.signed[:remember_me_token] && user_class.sorcery_adapter.find_by_remember_me_token(cookies.signed[:remember_me_token])
|
59
|
+
if user && user.has_remember_me_token?
|
60
|
+
set_remember_me_cookie!(user)
|
61
|
+
session[:user_id] = user.id.to_s
|
62
|
+
@current_user = user
|
63
|
+
else
|
64
|
+
@current_user = false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_remember_me_cookie!(user)
|
69
|
+
cookies.signed[:remember_me_token] = {
|
70
|
+
:value => user.send(user.sorcery_config.remember_me_token_attribute_name),
|
71
|
+
:expires => user.send(user.sorcery_config.remember_me_token_expires_at_attribute_name),
|
72
|
+
:httponly => Config.remember_me_httponly,
|
73
|
+
:domain => Config.cookie_domain
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module Controller
|
3
|
+
module Submodules
|
4
|
+
# This submodule helps you set a timeout to all user sessions.
|
5
|
+
# The timeout can be configured and also you can choose to reset it on every user action.
|
6
|
+
module SessionTimeout
|
7
|
+
def self.included(base)
|
8
|
+
base.send(:include, InstanceMethods)
|
9
|
+
Config.module_eval do
|
10
|
+
class << self
|
11
|
+
attr_accessor :session_timeout, # how long in seconds to keep the session alive.
|
12
|
+
|
13
|
+
:session_timeout_from_last_action # use the last action as the beginning of session
|
14
|
+
# timeout.
|
15
|
+
|
16
|
+
def merge_session_timeout_defaults!
|
17
|
+
@defaults.merge!(:@session_timeout => 3600, # 1.hour
|
18
|
+
:@session_timeout_from_last_action => false)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
merge_session_timeout_defaults!
|
22
|
+
end
|
23
|
+
Config.after_login << :register_login_time
|
24
|
+
base.prepend_before_filter :validate_session
|
25
|
+
end
|
26
|
+
|
27
|
+
module InstanceMethods
|
28
|
+
protected
|
29
|
+
|
30
|
+
# Registers last login to be used as the timeout starting point.
|
31
|
+
# Runs as a hook after a successful login.
|
32
|
+
def register_login_time(user, credentials)
|
33
|
+
session[:login_time] = session[:last_action_time] = Time.now.in_time_zone
|
34
|
+
end
|
35
|
+
|
36
|
+
# Checks if session timeout was reached and expires the current session if so.
|
37
|
+
# To be used as a before_filter, before require_login
|
38
|
+
def validate_session
|
39
|
+
session_to_use = Config.session_timeout_from_last_action ? session[:last_action_time] : session[:login_time]
|
40
|
+
if session_to_use && sorcery_session_expired?(session_to_use.to_time)
|
41
|
+
reset_sorcery_session
|
42
|
+
@current_user = nil
|
43
|
+
else
|
44
|
+
session[:last_action_time] = Time.now.in_time_zone
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def sorcery_session_expired?(time)
|
49
|
+
Time.now.in_time_zone - time > Config.session_timeout
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "openssl"
|
2
|
+
|
3
|
+
module Sorcery
|
4
|
+
module CryptoProviders
|
5
|
+
# This encryption method is reversible if you have the supplied key.
|
6
|
+
# So in 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 the following:
|
8
|
+
#
|
9
|
+
# Sorcery::Model::ConfigAES256.key = "my 32 bytes long key"
|
10
|
+
#
|
11
|
+
# My final comment is that this is a strong encryption method,
|
12
|
+
# but its main weakness is that its reversible. If you do not need to reverse the hash
|
13
|
+
# then you should consider Sha512 or BCrypt instead.
|
14
|
+
#
|
15
|
+
# Keep your key in a safe place, some even say the key should be stored on a separate server.
|
16
|
+
# This won't hurt performance because the only time it will try and access the key on the
|
17
|
+
# separate server is during initialization, which only
|
18
|
+
# happens once. The reasoning behind this is if someone does compromise your server they
|
19
|
+
# won't have the key also. Basically, you don't want to store the key with the lock.
|
20
|
+
class AES256
|
21
|
+
class << self
|
22
|
+
attr_writer :key
|
23
|
+
|
24
|
+
def encrypt(*tokens)
|
25
|
+
aes.encrypt
|
26
|
+
aes.key = @key
|
27
|
+
[aes.update(tokens.join) + aes.final].pack("m").chomp
|
28
|
+
end
|
29
|
+
|
30
|
+
def matches?(crypted, *tokens)
|
31
|
+
decrypt(crypted) == tokens.join
|
32
|
+
rescue OpenSSL::CipherError
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
def decrypt(crypted)
|
37
|
+
aes.decrypt
|
38
|
+
aes.key = @key
|
39
|
+
(aes.update(crypted.unpack("m").first) + aes.final)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def aes
|
45
|
+
raise ArgumentError.new("#{name} expects a 32 bytes long key. Please use Sorcery::Model::Config.encryption_key to set it.") if ( @key.nil? || @key == "" )
|
46
|
+
@aes ||= OpenSSL::Cipher::Cipher.new("AES-256-ECB")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'bcrypt'
|
2
|
+
|
3
|
+
module Sorcery
|
4
|
+
module CryptoProviders
|
5
|
+
# For most apps Sha512 is plenty secure, but if you are building an app that stores nuclear
|
6
|
+
# launch codes you might want to consier BCrypt. This is an extremely
|
7
|
+
# secure hashing algorithm, mainly because it is slow.
|
8
|
+
# A brute force attack on a BCrypt encrypted password would take much longer than a brute force attack on a
|
9
|
+
# password encrypted with a Sha algorithm. Keep in mind you are sacrificing performance by using this,
|
10
|
+
# generating a password takes exponentially longer than any
|
11
|
+
# of the Sha algorithms. I did some benchmarking to save you some time with your decision:
|
12
|
+
#
|
13
|
+
# require "bcrypt"
|
14
|
+
# require "digest"
|
15
|
+
# require "benchmark"
|
16
|
+
#
|
17
|
+
# Benchmark.bm(18) do |x|
|
18
|
+
# x.report("BCrypt (cost = 10:") { 100.times { BCrypt::Password.create("mypass", :cost => 10) } }
|
19
|
+
# x.report("BCrypt (cost = 2:") { 100.times { BCrypt::Password.create("mypass", :cost => 2) } }
|
20
|
+
# x.report("Sha512:") { 100.times { Digest::SHA512.hexdigest("mypass") } }
|
21
|
+
# x.report("Sha1:") { 100.times { Digest::SHA1.hexdigest("mypass") } }
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# user system total real
|
25
|
+
# BCrypt (cost = 10): 10.780000 0.060000 10.840000 ( 11.100289)
|
26
|
+
# BCrypt (cost = 2): 0.180000 0.000000 0.180000 ( 0.181914)
|
27
|
+
# Sha512: 0.000000 0.000000 0.000000 ( 0.000829)
|
28
|
+
# Sha1: 0.000000 0.000000 0.000000 ( 0.000395)
|
29
|
+
#
|
30
|
+
# You can play around with the cost to get that perfect balance between performance and security.
|
31
|
+
#
|
32
|
+
# Decided BCrypt is for you? Just insall the bcrypt gem:
|
33
|
+
#
|
34
|
+
# gem install bcrypt-ruby
|
35
|
+
#
|
36
|
+
# Update your initializer to use it:
|
37
|
+
#
|
38
|
+
# config.encryption_algorithm = :bcrypt
|
39
|
+
#
|
40
|
+
# You are good to go!
|
41
|
+
class BCrypt
|
42
|
+
class << self
|
43
|
+
# This is the :cost option for the BCrpyt library.
|
44
|
+
# The higher the cost the more secure it is and the longer is take the generate a hash. By default this is 10.
|
45
|
+
# Set this to whatever you want, play around with it to get that perfect balance between
|
46
|
+
# security and performance.
|
47
|
+
def cost
|
48
|
+
@cost ||= 10
|
49
|
+
end
|
50
|
+
attr_writer :cost
|
51
|
+
alias :stretches :cost
|
52
|
+
alias :stretches= :cost=
|
53
|
+
|
54
|
+
# Creates a BCrypt hash for the password passed.
|
55
|
+
def encrypt(*tokens)
|
56
|
+
::BCrypt::Password.create(join_tokens(tokens), :cost => cost)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Does the hash match the tokens? Uses the same tokens that were used to encrypt.
|
60
|
+
def matches?(hash, *tokens)
|
61
|
+
hash = new_from_hash(hash)
|
62
|
+
return false if hash.nil? || hash == {}
|
63
|
+
hash == join_tokens(tokens)
|
64
|
+
end
|
65
|
+
|
66
|
+
# This method is used as a flag to tell Sorcery to "resave" the password
|
67
|
+
# upon a successful login, using the new cost
|
68
|
+
def cost_matches?(hash)
|
69
|
+
hash = new_from_hash(hash)
|
70
|
+
if hash.nil? || hash == {}
|
71
|
+
false
|
72
|
+
else
|
73
|
+
hash.cost == cost
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def reset!
|
78
|
+
@cost = 10
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def join_tokens(tokens)
|
84
|
+
tokens.flatten.join
|
85
|
+
end
|
86
|
+
|
87
|
+
def new_from_hash(hash)
|
88
|
+
begin
|
89
|
+
::BCrypt::Password.new(hash)
|
90
|
+
rescue ::BCrypt::Errors::InvalidHash
|
91
|
+
return nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Sorcery
|
2
|
+
module CryptoProviders
|
3
|
+
module Common
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
class << self
|
7
|
+
attr_accessor :join_token
|
8
|
+
|
9
|
+
# The number of times to loop through the encryption.
|
10
|
+
def stretches
|
11
|
+
@stretches ||= 1
|
12
|
+
end
|
13
|
+
attr_writer :stretches
|
14
|
+
|
15
|
+
def encrypt(*tokens)
|
16
|
+
digest = tokens.flatten.compact.join(join_token)
|
17
|
+
stretches.times { digest = secure_digest(digest) }
|
18
|
+
digest
|
19
|
+
end
|
20
|
+
|
21
|
+
# Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
|
22
|
+
def matches?(crypted, *tokens)
|
23
|
+
encrypt(*tokens.compact) == crypted
|
24
|
+
end
|
25
|
+
|
26
|
+
def reset!
|
27
|
+
@stretches = 1
|
28
|
+
@join_token = nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
|
3
|
+
module Sorcery
|
4
|
+
module CryptoProviders
|
5
|
+
# This class was made for the users transitioning from md5 based systems.
|
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 Sorcery.
|
10
|
+
class MD5
|
11
|
+
include Common
|
12
|
+
class << self
|
13
|
+
def secure_digest(digest)
|
14
|
+
Digest::MD5.hexdigest(digest)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "digest/sha1"
|
2
|
+
|
3
|
+
module Sorcery
|
4
|
+
module CryptoProviders
|
5
|
+
# This class was made for the users transitioning from restful_authentication. I highly discourage using this
|
6
|
+
# crypto provider as it inferior to your other options. Please use any other provider offered by Sorcery.
|
7
|
+
class SHA1
|
8
|
+
include Common
|
9
|
+
class << self
|
10
|
+
def join_token
|
11
|
+
@join_token ||= "--"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Turns your raw password into a Sha1 hash.
|
15
|
+
def encrypt(*tokens)
|
16
|
+
tokens = tokens.flatten
|
17
|
+
digest = tokens.shift
|
18
|
+
stretches.times { digest = secure_digest([digest, *tokens].join(join_token)) }
|
19
|
+
digest
|
20
|
+
end
|
21
|
+
|
22
|
+
def secure_digest(digest)
|
23
|
+
Digest::SHA1.hexdigest(digest)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "digest/sha2"
|
2
|
+
|
3
|
+
module Sorcery
|
4
|
+
# The activate_sorcery method has a custom_crypto_provider configuration option.
|
5
|
+
# This allows you to use any type of encryption you like.
|
6
|
+
# Just create a class with a class 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 is irrelevant,
|
13
|
+
# # just do what you need to do with them and return a single encrypted string.
|
14
|
+
# # for example, you will most likely join all of the objects into a single string and then encrypt that string
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def self.matches?(crypted, *tokens)
|
18
|
+
# # return true if the crypted string matches the tokens.
|
19
|
+
# # depending on your algorithm you might decrypt the string then compare it to the token, or you might
|
20
|
+
# # encrypt the tokens and make sure it matches the crypted string, its up to you
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
module CryptoProviders
|
24
|
+
# = Sha256
|
25
|
+
#
|
26
|
+
# Uses the Sha256 hash algorithm to encrypt passwords.
|
27
|
+
class SHA256
|
28
|
+
include Common
|
29
|
+
class << self
|
30
|
+
def secure_digest(digest)
|
31
|
+
Digest::SHA256.hexdigest(digest)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "digest/sha2"
|
2
|
+
|
3
|
+
module Sorcery
|
4
|
+
# The activate_sorcery method has a custom_crypto_provider configuration option.
|
5
|
+
# This allows you to use any type of encryption you like.
|
6
|
+
# Just create a class with a class 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 is irrelevant,
|
13
|
+
# # just do what you need to do with them and return a single encrypted string.
|
14
|
+
# # for example, you will most likely join all of the objects into a single string and then encrypt that string
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def self.matches?(crypted, *tokens)
|
18
|
+
# # return true if the crypted string matches the tokens.
|
19
|
+
# # depending on your algorithm you might decrypt the string then compare it to the token, or you might
|
20
|
+
# # encrypt the tokens and make sure it matches the crypted string, its up to you
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
module CryptoProviders
|
24
|
+
# = Sha512
|
25
|
+
#
|
26
|
+
# Uses the Sha512 hash algorithm to encrypt passwords.
|
27
|
+
class SHA512
|
28
|
+
include Common
|
29
|
+
class << self
|
30
|
+
def secure_digest(digest)
|
31
|
+
Digest::SHA512.hexdigest(digest)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|