sorcery 0.11.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE.md +20 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +5 -0
- data/.github/workflows/ruby.yml +23 -0
- data/.rubocop.yml +55 -0
- data/.rubocop_todo.yml +155 -0
- data/.travis.yml +11 -51
- data/CHANGELOG.md +75 -0
- data/CODE_OF_CONDUCT.md +14 -0
- data/Gemfile +2 -2
- data/{LICENSE.txt → LICENSE.md} +1 -1
- data/README.md +34 -7
- data/SECURITY.md +18 -0
- data/gemfiles/rails_52.gemfile +7 -0
- data/gemfiles/rails_60.gemfile +7 -0
- data/lib/generators/sorcery/USAGE +1 -1
- data/lib/generators/sorcery/helpers.rb +4 -0
- data/lib/generators/sorcery/install_generator.rb +21 -21
- data/lib/generators/sorcery/templates/initializer.rb +176 -69
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +5 -5
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +4 -4
- data/lib/generators/sorcery/templates/migration/core.rb +4 -4
- data/lib/generators/sorcery/templates/migration/external.rb +3 -3
- data/lib/generators/sorcery/templates/migration/magic_login.rb +9 -0
- data/lib/generators/sorcery/templates/migration/remember_me.rb +3 -3
- data/lib/generators/sorcery/templates/migration/reset_password.rb +5 -4
- data/lib/generators/sorcery/templates/migration/user_activation.rb +4 -4
- data/lib/sorcery.rb +2 -0
- data/lib/sorcery/adapters/active_record_adapter.rb +4 -3
- data/lib/sorcery/adapters/mongoid_adapter.rb +23 -11
- data/lib/sorcery/controller.rb +26 -15
- data/lib/sorcery/controller/config.rb +7 -5
- data/lib/sorcery/controller/submodules/activity_logging.rb +9 -3
- data/lib/sorcery/controller/submodules/external.rb +52 -33
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +2 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +3 -8
- data/lib/sorcery/controller/submodules/session_timeout.rb +28 -5
- data/lib/sorcery/crypto_providers/aes256.rb +2 -1
- data/lib/sorcery/crypto_providers/bcrypt.rb +8 -2
- data/lib/sorcery/engine.rb +16 -3
- data/lib/sorcery/model.rb +14 -10
- data/lib/sorcery/model/config.rb +12 -4
- data/lib/sorcery/model/submodules/brute_force_protection.rb +6 -7
- data/lib/sorcery/model/submodules/external.rb +19 -3
- data/lib/sorcery/model/submodules/magic_login.rb +130 -0
- data/lib/sorcery/model/submodules/reset_password.rb +25 -2
- data/lib/sorcery/model/submodules/user_activation.rb +1 -1
- data/lib/sorcery/model/temporary_token.rb +3 -1
- data/lib/sorcery/protocols/oauth.rb +1 -0
- data/lib/sorcery/providers/auth0.rb +46 -0
- data/lib/sorcery/providers/battlenet.rb +51 -0
- data/lib/sorcery/providers/discord.rb +52 -0
- data/lib/sorcery/providers/heroku.rb +1 -0
- data/lib/sorcery/providers/instagram.rb +73 -0
- data/lib/sorcery/providers/line.rb +63 -0
- data/lib/sorcery/providers/linkedin.rb +45 -36
- data/lib/sorcery/providers/vk.rb +5 -4
- data/lib/sorcery/providers/wechat.rb +8 -6
- data/lib/sorcery/test_helpers/internal.rb +5 -4
- data/lib/sorcery/test_helpers/internal/rails.rb +11 -11
- data/lib/sorcery/test_helpers/rails/request.rb +20 -0
- data/lib/sorcery/version.rb +1 -1
- data/sorcery.gemspec +26 -10
- data/spec/active_record/user_activation_spec.rb +2 -2
- data/spec/active_record/user_activity_logging_spec.rb +2 -2
- data/spec/active_record/user_brute_force_protection_spec.rb +2 -2
- data/spec/active_record/user_magic_login_spec.rb +15 -0
- data/spec/active_record/user_oauth_spec.rb +2 -2
- data/spec/active_record/user_remember_me_spec.rb +2 -2
- data/spec/active_record/user_reset_password_spec.rb +2 -2
- data/spec/active_record/user_spec.rb +0 -10
- data/spec/controllers/controller_http_basic_auth_spec.rb +1 -1
- data/spec/controllers/controller_oauth2_spec.rb +230 -123
- data/spec/controllers/controller_oauth_spec.rb +13 -7
- data/spec/controllers/controller_remember_me_spec.rb +16 -8
- data/spec/controllers/controller_session_timeout_spec.rb +90 -3
- data/spec/controllers/controller_spec.rb +13 -3
- data/spec/orm/active_record.rb +2 -2
- data/spec/providers/example_provider_spec.rb +17 -0
- data/spec/providers/example_spec.rb +17 -0
- data/spec/providers/vk_spec.rb +42 -0
- data/spec/rails_app/app/assets/config/manifest.js +1 -0
- data/spec/rails_app/app/controllers/application_controller.rb +2 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +152 -33
- data/spec/rails_app/app/mailers/sorcery_mailer.rb +7 -0
- data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.html.erb +13 -0
- data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.text.erb +6 -0
- data/spec/rails_app/config/application.rb +8 -3
- data/spec/rails_app/config/boot.rb +1 -1
- data/spec/rails_app/config/environment.rb +1 -1
- data/spec/rails_app/config/routes.rb +17 -0
- data/spec/rails_app/config/secrets.yml +4 -0
- data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +2 -2
- data/spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb +9 -0
- data/spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb +17 -0
- data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +2 -0
- data/spec/rails_app/db/schema.rb +7 -9
- data/spec/shared_examples/user_magic_login_shared_examples.rb +150 -0
- data/spec/shared_examples/user_oauth_shared_examples.rb +1 -1
- data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -1
- data/spec/shared_examples/user_reset_password_shared_examples.rb +37 -5
- data/spec/shared_examples/user_shared_examples.rb +104 -43
- data/spec/sorcery_crypto_providers_spec.rb +61 -1
- data/spec/sorcery_temporary_token_spec.rb +27 -0
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/migration_helper.rb +29 -0
- data/spec/support/providers/example.rb +11 -0
- data/spec/support/providers/example_provider.rb +11 -0
- metadata +92 -29
- data/gemfiles/active_record-rails40.gemfile +0 -7
- data/gemfiles/active_record-rails41.gemfile +0 -7
- data/gemfiles/active_record-rails42.gemfile +0 -7
- data/spec/rails_app/config/initializers/secret_token.rb +0 -7
@@ -54,6 +54,13 @@ shared_examples_for 'rails_3_core_model' do
|
|
54
54
|
expect(User.sorcery_config.custom_encryption_provider).to eq Array
|
55
55
|
end
|
56
56
|
|
57
|
+
it "enables configuration option 'pepper'" do
|
58
|
+
pepper = '*$%&%*++'
|
59
|
+
sorcery_model_property_set(:pepper, pepper)
|
60
|
+
|
61
|
+
expect(User.sorcery_config.pepper).to eq pepper
|
62
|
+
end
|
63
|
+
|
57
64
|
it "enables configuration option 'salt_join_token'" do
|
58
65
|
salt_join_token = '--%%*&-'
|
59
66
|
sorcery_model_property_set(:salt_join_token, salt_join_token)
|
@@ -228,10 +235,13 @@ shared_examples_for 'rails_3_core_model' do
|
|
228
235
|
|
229
236
|
expect(user).to receive(:save) { raise RuntimeError }
|
230
237
|
|
238
|
+
# rubocop:disable Lint/HandleExceptions
|
231
239
|
begin
|
232
240
|
user.save
|
233
|
-
rescue
|
241
|
+
rescue RuntimeError
|
242
|
+
# Intentionally force exception during save
|
234
243
|
end
|
244
|
+
# rubocop:enable Lint/HandleExceptions
|
235
245
|
|
236
246
|
expect(user.password).not_to be_nil
|
237
247
|
end
|
@@ -308,12 +318,12 @@ shared_examples_for 'rails_3_core_model' do
|
|
308
318
|
|
309
319
|
describe 'generic send email' do
|
310
320
|
before(:all) do
|
311
|
-
|
321
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/activation")
|
312
322
|
User.reset_column_information
|
313
323
|
end
|
314
324
|
|
315
325
|
after(:all) do
|
316
|
-
|
326
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/activation")
|
317
327
|
end
|
318
328
|
|
319
329
|
before do
|
@@ -323,9 +333,11 @@ shared_examples_for 'rails_3_core_model' do
|
|
323
333
|
|
324
334
|
it 'use deliver_later' do
|
325
335
|
sorcery_reload!(
|
326
|
-
[
|
327
|
-
|
328
|
-
|
336
|
+
%i[
|
337
|
+
user_activation
|
338
|
+
user_activation_mailer
|
339
|
+
activation_needed_email_method_name
|
340
|
+
email_delivery_method
|
329
341
|
],
|
330
342
|
user_activation_mailer: SorceryMailer,
|
331
343
|
activation_needed_email_method_name: nil,
|
@@ -340,9 +352,10 @@ shared_examples_for 'rails_3_core_model' do
|
|
340
352
|
it 'use deliver_now if rails version 4.2+' do
|
341
353
|
allow(Rails).to receive(:version).and_return('4.2.0')
|
342
354
|
sorcery_reload!(
|
343
|
-
[
|
344
|
-
|
345
|
-
|
355
|
+
%i[
|
356
|
+
user_activation
|
357
|
+
user_activation_mailer
|
358
|
+
activation_needed_email_method_name
|
346
359
|
],
|
347
360
|
user_activation_mailer: SorceryMailer,
|
348
361
|
activation_needed_email_method_name: nil
|
@@ -355,9 +368,10 @@ shared_examples_for 'rails_3_core_model' do
|
|
355
368
|
it 'use deliver if rails version < 4.2' do
|
356
369
|
allow(Rails).to receive(:version).and_return('4.1.0')
|
357
370
|
sorcery_reload!(
|
358
|
-
[
|
359
|
-
|
360
|
-
|
371
|
+
%i[
|
372
|
+
user_activation
|
373
|
+
user_activation_mailer
|
374
|
+
activation_needed_email_method_name
|
361
375
|
],
|
362
376
|
user_activation_mailer: SorceryMailer,
|
363
377
|
activation_needed_email_method_name: nil
|
@@ -452,6 +466,14 @@ shared_examples_for 'rails_3_core_model' do
|
|
452
466
|
expect(User.encrypt(@text)).to eq Sorcery::CryptoProviders::SHA512.encrypt(@text)
|
453
467
|
end
|
454
468
|
|
469
|
+
it 'if encryption algo is bcrypt it works' do
|
470
|
+
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
471
|
+
|
472
|
+
# comparison is done using BCrypt::Password#==(raw_token), not by String#==
|
473
|
+
expect(User.encrypt(@text)).to be_an_instance_of BCrypt::Password
|
474
|
+
expect(User.encrypt(@text)).to eq @text
|
475
|
+
end
|
476
|
+
|
455
477
|
it 'salt is random for each user and saved in db' do
|
456
478
|
sorcery_model_property_set(:salt_attribute_name, :salt)
|
457
479
|
|
@@ -481,6 +503,54 @@ shared_examples_for 'rails_3_core_model' do
|
|
481
503
|
|
482
504
|
expect(user.crypted_password).to eq Sorcery::CryptoProviders::SHA512.encrypt('secret', user.salt)
|
483
505
|
end
|
506
|
+
|
507
|
+
it 'if pepper is set uses it to encrypt' do
|
508
|
+
sorcery_model_property_set(:salt_attribute_name, :salt)
|
509
|
+
sorcery_model_property_set(:pepper, '++@^$')
|
510
|
+
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
511
|
+
|
512
|
+
# password comparison is done using BCrypt::Password#==(raw_token), not String#==
|
513
|
+
bcrypt_password = BCrypt::Password.new(user.crypted_password)
|
514
|
+
allow(::BCrypt::Password).to receive(:create) do |token, options = {}|
|
515
|
+
# need to use common BCrypt's salt when genarating BCrypt::Password objects
|
516
|
+
# so that any generated password hashes can be compared each other
|
517
|
+
::BCrypt::Engine.hash_secret(token, bcrypt_password.salt)
|
518
|
+
end
|
519
|
+
|
520
|
+
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret')
|
521
|
+
|
522
|
+
Sorcery::CryptoProviders::BCrypt.pepper = ''
|
523
|
+
|
524
|
+
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
525
|
+
|
526
|
+
Sorcery::CryptoProviders::BCrypt.pepper = User.sorcery_config.pepper
|
527
|
+
|
528
|
+
expect(user.crypted_password).to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
529
|
+
end
|
530
|
+
|
531
|
+
it 'if pepper is empty string (default) does not use pepper to encrypt' do
|
532
|
+
sorcery_model_property_set(:salt_attribute_name, :salt)
|
533
|
+
sorcery_model_property_set(:pepper, '')
|
534
|
+
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
535
|
+
|
536
|
+
# password comparison is done using BCrypt::Password#==(raw_token), not String#==
|
537
|
+
bcrypt_password = BCrypt::Password.new(user.crypted_password)
|
538
|
+
allow(::BCrypt::Password).to receive(:create) do |token, options = {}|
|
539
|
+
# need to use common BCrypt's salt when genarating BCrypt::Password objects
|
540
|
+
# so that any generated password hashes can be compared each other
|
541
|
+
::BCrypt::Engine.hash_secret(token, bcrypt_password.salt)
|
542
|
+
end
|
543
|
+
|
544
|
+
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret')
|
545
|
+
|
546
|
+
Sorcery::CryptoProviders::BCrypt.pepper = 'some_pepper'
|
547
|
+
|
548
|
+
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
549
|
+
|
550
|
+
Sorcery::CryptoProviders::BCrypt.pepper = User.sorcery_config.pepper
|
551
|
+
|
552
|
+
expect(user.crypted_password).to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
553
|
+
end
|
484
554
|
end
|
485
555
|
|
486
556
|
describe 'ORM adapter' do
|
@@ -503,7 +573,7 @@ shared_examples_for 'rails_3_core_model' do
|
|
503
573
|
end
|
504
574
|
|
505
575
|
it 'find_by_username works as expected with multiple username attributes' do
|
506
|
-
sorcery_model_property_set(:username_attribute_names, [
|
576
|
+
sorcery_model_property_set(:username_attribute_names, %i[username email])
|
507
577
|
|
508
578
|
expect(User.sorcery_adapter.find_by_username('gizmo')).to eq user
|
509
579
|
end
|
@@ -518,6 +588,21 @@ shared_examples_for 'external_user' do
|
|
518
588
|
let(:user) { create_new_user }
|
519
589
|
let(:external_user) { create_new_external_user :twitter }
|
520
590
|
|
591
|
+
before(:all) do
|
592
|
+
if SORCERY_ORM == :active_record
|
593
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/external")
|
594
|
+
MigrationHelper.migrate("#{Rails.root}/db/migrate/activation")
|
595
|
+
end
|
596
|
+
sorcery_reload!
|
597
|
+
end
|
598
|
+
|
599
|
+
after(:all) do
|
600
|
+
if SORCERY_ORM == :active_record
|
601
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/external")
|
602
|
+
MigrationHelper.rollback("#{Rails.root}/db/migrate/activation")
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
521
606
|
before(:each) do
|
522
607
|
User.sorcery_adapter.delete_all
|
523
608
|
end
|
@@ -535,24 +620,12 @@ shared_examples_for 'external_user' do
|
|
535
620
|
end
|
536
621
|
|
537
622
|
describe '.create_from_provider' do
|
538
|
-
before(:
|
539
|
-
if SORCERY_ORM == :active_record
|
540
|
-
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
|
541
|
-
User.reset_column_information
|
542
|
-
end
|
543
|
-
|
623
|
+
before(:each) do
|
544
624
|
sorcery_reload!([:external])
|
545
|
-
|
546
|
-
|
547
|
-
after(:all) do
|
548
|
-
if SORCERY_ORM == :active_record
|
549
|
-
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
|
550
|
-
end
|
625
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
551
626
|
end
|
552
627
|
|
553
628
|
it 'supports nested attributes' do
|
554
|
-
sorcery_model_property_set(:authentications_class, Authentication)
|
555
|
-
|
556
629
|
expect do
|
557
630
|
User.create_from_provider('facebook', '123', username: 'Noam Ben Ari')
|
558
631
|
end.to change { User.count }.by(1)
|
@@ -570,33 +643,21 @@ shared_examples_for 'external_user' do
|
|
570
643
|
it 'does not create user when block return false' do
|
571
644
|
expect do
|
572
645
|
User.create_from_provider('facebook', '123', username: 'Noam Ben Ari') { false }
|
573
|
-
end.not_to
|
646
|
+
end.not_to(change { User.count })
|
574
647
|
end
|
575
648
|
end
|
576
649
|
end
|
577
650
|
|
578
651
|
describe 'activation' do
|
579
|
-
before(:
|
580
|
-
|
581
|
-
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
|
582
|
-
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activation")
|
583
|
-
end
|
584
|
-
|
585
|
-
sorcery_reload!([:user_activation, :external], user_activation_mailer: ::SorceryMailer)
|
586
|
-
end
|
587
|
-
|
588
|
-
after(:all) do
|
589
|
-
if SORCERY_ORM == :active_record
|
590
|
-
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
|
591
|
-
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activation")
|
592
|
-
end
|
652
|
+
before(:each) do
|
653
|
+
sorcery_reload!(%i[user_activation external], user_activation_mailer: ::SorceryMailer)
|
593
654
|
end
|
594
655
|
|
595
656
|
after(:each) do
|
596
657
|
User.sorcery_adapter.delete_all
|
597
658
|
end
|
598
659
|
|
599
|
-
[
|
660
|
+
%i[facebook github google liveid slack].each do |provider|
|
600
661
|
it 'does not send activation email to external users' do
|
601
662
|
old_size = ActionMailer::Base.deliveries.size
|
602
663
|
create_new_external_user(provider)
|
@@ -53,7 +53,7 @@ describe 'Crypto Providers wrappers' do
|
|
53
53
|
|
54
54
|
it 'matches password encrypted using salt and join token from upstream' do
|
55
55
|
Sorcery::CryptoProviders::SHA1.join_token = 'test'
|
56
|
-
expect(Sorcery::CryptoProviders::SHA1.encrypt(%w
|
56
|
+
expect(Sorcery::CryptoProviders::SHA1.encrypt(%w[password gq18WBnJYNh2arkC1kgH])).to eq '894b5bf1643b8d0e1b2eaddb22426be7036dab70'
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
@@ -148,6 +148,7 @@ describe 'Crypto Providers wrappers' do
|
|
148
148
|
before(:all) do
|
149
149
|
Sorcery::CryptoProviders::BCrypt.cost = 1
|
150
150
|
@digest = BCrypt::Password.create('Noam Ben-Ari', cost: Sorcery::CryptoProviders::BCrypt.cost)
|
151
|
+
@tokens = %w[password gq18WBnJYNh2arkC1kgH]
|
151
152
|
end
|
152
153
|
|
153
154
|
after(:each) do
|
@@ -181,5 +182,64 @@ describe 'Crypto Providers wrappers' do
|
|
181
182
|
# stubbed in Sorcery::TestHelpers::Internal
|
182
183
|
expect(Sorcery::CryptoProviders::BCrypt.cost).to eq 1
|
183
184
|
end
|
185
|
+
|
186
|
+
it 'matches token encrypted with salt from upstream' do
|
187
|
+
# note: actual comparison is done by BCrypt::Password#==(raw_token)
|
188
|
+
expect(Sorcery::CryptoProviders::BCrypt.encrypt(@tokens)).to eq @tokens.flatten.join
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'respond_to?(:pepper) returns true' do
|
192
|
+
expect(Sorcery::CryptoProviders::BCrypt.respond_to?(:pepper)).to be true
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'when pepper is provided' do
|
196
|
+
before(:each) do
|
197
|
+
Sorcery::CryptoProviders::BCrypt.pepper = 'pepper'
|
198
|
+
@digest = Sorcery::CryptoProviders::BCrypt.encrypt(@tokens) # a BCrypt::Password object
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'matches token encrypted with salt and pepper from upstream' do
|
202
|
+
# note: actual comparison is done by BCrypt::Password#==(raw_token)
|
203
|
+
expect(@digest).to eq @tokens.flatten.join.concat('pepper')
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'matches? returns true when matches' do
|
207
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, *@tokens)).to be true
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'matches? returns false when pepper is replaced with empty string' do
|
211
|
+
Sorcery::CryptoProviders::BCrypt.pepper = ''
|
212
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, *@tokens)).to be false
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'matches? returns false when no match' do
|
216
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, 'a_random_incorrect_password')).to be false
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context "when pepper is an empty string (default)" do
|
221
|
+
before(:each) do
|
222
|
+
Sorcery::CryptoProviders::BCrypt.pepper = ''
|
223
|
+
@digest = Sorcery::CryptoProviders::BCrypt.encrypt(@tokens) # a BCrypt::Password object
|
224
|
+
end
|
225
|
+
|
226
|
+
# make sure the default pepper '' does nothing
|
227
|
+
it 'matches token encrypted with salt only (without pepper)' do
|
228
|
+
expect(@digest).to eq @tokens.flatten.join # keep consistency with the older versions of #join_token
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'matches? returns true when matches' do
|
232
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, *@tokens)).to be true
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'matches? returns false when pepper has changed' do
|
236
|
+
Sorcery::CryptoProviders::BCrypt.pepper = 'a new pepper'
|
237
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, *@tokens)).to be false
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'matches? returns false when no match' do
|
241
|
+
expect(Sorcery::CryptoProviders::BCrypt.matches?(@digest, 'a_random_incorrect_password')).to be false
|
242
|
+
end
|
243
|
+
end
|
184
244
|
end
|
185
245
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sorcery::Model::TemporaryToken do
|
4
|
+
describe '.generate_random_token' do
|
5
|
+
before do
|
6
|
+
sorcery_reload!
|
7
|
+
end
|
8
|
+
|
9
|
+
subject { Sorcery::Model::TemporaryToken.generate_random_token.length }
|
10
|
+
|
11
|
+
context 'token_randomness is 3' do
|
12
|
+
before do
|
13
|
+
sorcery_model_property_set(:token_randomness, 3)
|
14
|
+
end
|
15
|
+
|
16
|
+
it { is_expected.to eq 4 }
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'token_randomness is 15' do
|
20
|
+
before do
|
21
|
+
sorcery_model_property_set(:token_randomness, 15)
|
22
|
+
end
|
23
|
+
|
24
|
+
it { is_expected.to eq 20 }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec.opts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
--color
|
2
|
-
--format documentation
|
2
|
+
--format documentation
|
data/spec/spec_helper.rb
CHANGED
@@ -29,7 +29,7 @@ RSpec.configure do |config|
|
|
29
29
|
config.include RSpec::Rails::ControllerExampleGroup, file_path: /controller(.)*_spec.rb$/
|
30
30
|
config.mock_with :rspec
|
31
31
|
|
32
|
-
config.use_transactional_fixtures =
|
32
|
+
config.use_transactional_fixtures = false
|
33
33
|
|
34
34
|
config.before(:suite) { setup_orm }
|
35
35
|
config.after(:suite) { teardown_orm }
|
@@ -40,7 +40,7 @@ RSpec.configure do |config|
|
|
40
40
|
|
41
41
|
if begin
|
42
42
|
Module.const_defined?('::Rails::Controller::Testing')
|
43
|
-
rescue
|
43
|
+
rescue StandardError
|
44
44
|
false
|
45
45
|
end
|
46
46
|
config.include ::Rails::Controller::Testing::TestProcess, type: :controller
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class MigrationHelper
|
2
|
+
class << self
|
3
|
+
def migrate(path)
|
4
|
+
if ActiveRecord.version >= Gem::Version.new('6.0.0')
|
5
|
+
ActiveRecord::MigrationContext.new(path, schema_migration).migrate
|
6
|
+
elsif ActiveRecord.version >= Gem::Version.new('5.2.0')
|
7
|
+
ActiveRecord::MigrationContext.new(path).migrate
|
8
|
+
else
|
9
|
+
ActiveRecord::Migrator.migrate(path)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def rollback(path)
|
14
|
+
if ActiveRecord.version >= Gem::Version.new('6.0.0')
|
15
|
+
ActiveRecord::MigrationContext.new(path, schema_migration).rollback
|
16
|
+
elsif ActiveRecord.version >= Gem::Version.new('5.2.0')
|
17
|
+
ActiveRecord::MigrationContext.new(path).rollback
|
18
|
+
else
|
19
|
+
ActiveRecord::Migrator.rollback(path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def schema_migration
|
26
|
+
ActiveRecord::Base.connection.schema_migration
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,18 +1,33 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sorcery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noam Ben Ari
|
8
8
|
- Kir Shatrov
|
9
9
|
- Grzegorz Witek
|
10
10
|
- Chase Gilliam
|
11
|
+
- Josh Buker
|
11
12
|
autorequire:
|
12
13
|
bindir: bin
|
13
14
|
cert_chain: []
|
14
|
-
date:
|
15
|
+
date: 2021-02-16 00:00:00.000000000 Z
|
15
16
|
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: bcrypt
|
19
|
+
requirement: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - "~>"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '3.1'
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '3.1'
|
16
31
|
- !ruby/object:Gem::Dependency
|
17
32
|
name: oauth
|
18
33
|
requirement: !ruby/object:Gem::Requirement
|
@@ -54,35 +69,35 @@ dependencies:
|
|
54
69
|
- !ruby/object:Gem::Version
|
55
70
|
version: 0.8.0
|
56
71
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
72
|
+
name: byebug
|
58
73
|
requirement: !ruby/object:Gem::Requirement
|
59
74
|
requirements:
|
60
75
|
- - "~>"
|
61
76
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
63
|
-
type: :
|
77
|
+
version: 10.0.0
|
78
|
+
type: :development
|
64
79
|
prerelease: false
|
65
80
|
version_requirements: !ruby/object:Gem::Requirement
|
66
81
|
requirements:
|
67
82
|
- - "~>"
|
68
83
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
84
|
+
version: 10.0.0
|
70
85
|
- !ruby/object:Gem::Dependency
|
71
|
-
name:
|
86
|
+
name: rspec-rails
|
72
87
|
requirement: !ruby/object:Gem::Requirement
|
73
88
|
requirements:
|
74
89
|
- - "~>"
|
75
90
|
- !ruby/object:Gem::Version
|
76
|
-
version:
|
91
|
+
version: 3.7.0
|
77
92
|
type: :development
|
78
93
|
prerelease: false
|
79
94
|
version_requirements: !ruby/object:Gem::Requirement
|
80
95
|
requirements:
|
81
96
|
- - "~>"
|
82
97
|
- !ruby/object:Gem::Version
|
83
|
-
version:
|
98
|
+
version: 3.7.0
|
84
99
|
- !ruby/object:Gem::Dependency
|
85
|
-
name:
|
100
|
+
name: rubocop
|
86
101
|
requirement: !ruby/object:Gem::Requirement
|
87
102
|
requirements:
|
88
103
|
- - ">="
|
@@ -110,66 +125,93 @@ dependencies:
|
|
110
125
|
- !ruby/object:Gem::Version
|
111
126
|
version: 0.3.8
|
112
127
|
- !ruby/object:Gem::Dependency
|
113
|
-
name:
|
128
|
+
name: test-unit
|
114
129
|
requirement: !ruby/object:Gem::Requirement
|
115
130
|
requirements:
|
116
131
|
- - "~>"
|
117
132
|
- !ruby/object:Gem::Version
|
118
|
-
version: 3.
|
133
|
+
version: 3.2.0
|
119
134
|
type: :development
|
120
135
|
prerelease: false
|
121
136
|
version_requirements: !ruby/object:Gem::Requirement
|
122
137
|
requirements:
|
123
138
|
- - "~>"
|
124
139
|
- !ruby/object:Gem::Version
|
125
|
-
version: 3.
|
140
|
+
version: 3.2.0
|
126
141
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
142
|
+
name: timecop
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
type: :development
|
149
|
+
prerelease: false
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: webmock
|
128
157
|
requirement: !ruby/object:Gem::Requirement
|
129
158
|
requirements:
|
130
159
|
- - "~>"
|
131
160
|
- !ruby/object:Gem::Version
|
132
|
-
version: 3.
|
161
|
+
version: 3.3.0
|
133
162
|
type: :development
|
134
163
|
prerelease: false
|
135
164
|
version_requirements: !ruby/object:Gem::Requirement
|
136
165
|
requirements:
|
137
166
|
- - "~>"
|
138
167
|
- !ruby/object:Gem::Version
|
139
|
-
version: 3.
|
168
|
+
version: 3.3.0
|
140
169
|
- !ruby/object:Gem::Dependency
|
141
|
-
name:
|
170
|
+
name: yard
|
142
171
|
requirement: !ruby/object:Gem::Requirement
|
143
172
|
requirements:
|
144
173
|
- - "~>"
|
145
174
|
- !ruby/object:Gem::Version
|
146
|
-
version: 9.0
|
175
|
+
version: 0.9.0
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: 0.9.12
|
147
179
|
type: :development
|
148
180
|
prerelease: false
|
149
181
|
version_requirements: !ruby/object:Gem::Requirement
|
150
182
|
requirements:
|
151
183
|
- - "~>"
|
152
184
|
- !ruby/object:Gem::Version
|
153
|
-
version: 9.0
|
185
|
+
version: 0.9.0
|
186
|
+
- - ">="
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: 0.9.12
|
154
189
|
description: Provides common authentication needs such as signing in/out, activating
|
155
190
|
by email and resetting password.
|
156
|
-
email:
|
191
|
+
email:
|
192
|
+
- crypto@joshbuker.com
|
157
193
|
executables: []
|
158
194
|
extensions: []
|
159
195
|
extra_rdoc_files: []
|
160
196
|
files:
|
161
197
|
- ".document"
|
198
|
+
- ".github/ISSUE_TEMPLATE.md"
|
199
|
+
- ".github/PULL_REQUEST_TEMPLATE.md"
|
200
|
+
- ".github/workflows/ruby.yml"
|
162
201
|
- ".gitignore"
|
163
202
|
- ".rspec"
|
203
|
+
- ".rubocop.yml"
|
204
|
+
- ".rubocop_todo.yml"
|
164
205
|
- ".travis.yml"
|
165
206
|
- CHANGELOG.md
|
207
|
+
- CODE_OF_CONDUCT.md
|
166
208
|
- Gemfile
|
167
|
-
- LICENSE.
|
209
|
+
- LICENSE.md
|
168
210
|
- README.md
|
169
211
|
- Rakefile
|
170
|
-
-
|
171
|
-
- gemfiles/
|
172
|
-
- gemfiles/
|
212
|
+
- SECURITY.md
|
213
|
+
- gemfiles/rails_52.gemfile
|
214
|
+
- gemfiles/rails_60.gemfile
|
173
215
|
- lib/generators/sorcery/USAGE
|
174
216
|
- lib/generators/sorcery/helpers.rb
|
175
217
|
- lib/generators/sorcery/install_generator.rb
|
@@ -178,6 +220,7 @@ files:
|
|
178
220
|
- lib/generators/sorcery/templates/migration/brute_force_protection.rb
|
179
221
|
- lib/generators/sorcery/templates/migration/core.rb
|
180
222
|
- lib/generators/sorcery/templates/migration/external.rb
|
223
|
+
- lib/generators/sorcery/templates/migration/magic_login.rb
|
181
224
|
- lib/generators/sorcery/templates/migration/remember_me.rb
|
182
225
|
- lib/generators/sorcery/templates/migration/reset_password.rb
|
183
226
|
- lib/generators/sorcery/templates/migration/user_activation.rb
|
@@ -206,6 +249,7 @@ files:
|
|
206
249
|
- lib/sorcery/model/submodules/activity_logging.rb
|
207
250
|
- lib/sorcery/model/submodules/brute_force_protection.rb
|
208
251
|
- lib/sorcery/model/submodules/external.rb
|
252
|
+
- lib/sorcery/model/submodules/magic_login.rb
|
209
253
|
- lib/sorcery/model/submodules/remember_me.rb
|
210
254
|
- lib/sorcery/model/submodules/reset_password.rb
|
211
255
|
- lib/sorcery/model/submodules/user_activation.rb
|
@@ -213,12 +257,17 @@ files:
|
|
213
257
|
- lib/sorcery/protocols/certs/ca-bundle.crt
|
214
258
|
- lib/sorcery/protocols/oauth.rb
|
215
259
|
- lib/sorcery/protocols/oauth2.rb
|
260
|
+
- lib/sorcery/providers/auth0.rb
|
216
261
|
- lib/sorcery/providers/base.rb
|
262
|
+
- lib/sorcery/providers/battlenet.rb
|
263
|
+
- lib/sorcery/providers/discord.rb
|
217
264
|
- lib/sorcery/providers/facebook.rb
|
218
265
|
- lib/sorcery/providers/github.rb
|
219
266
|
- lib/sorcery/providers/google.rb
|
220
267
|
- lib/sorcery/providers/heroku.rb
|
268
|
+
- lib/sorcery/providers/instagram.rb
|
221
269
|
- lib/sorcery/providers/jira.rb
|
270
|
+
- lib/sorcery/providers/line.rb
|
222
271
|
- lib/sorcery/providers/linkedin.rb
|
223
272
|
- lib/sorcery/providers/liveid.rb
|
224
273
|
- lib/sorcery/providers/microsoft.rb
|
@@ -233,11 +282,13 @@ files:
|
|
233
282
|
- lib/sorcery/test_helpers/internal/rails.rb
|
234
283
|
- lib/sorcery/test_helpers/rails/controller.rb
|
235
284
|
- lib/sorcery/test_helpers/rails/integration.rb
|
285
|
+
- lib/sorcery/test_helpers/rails/request.rb
|
236
286
|
- lib/sorcery/version.rb
|
237
287
|
- sorcery.gemspec
|
238
288
|
- spec/active_record/user_activation_spec.rb
|
239
289
|
- spec/active_record/user_activity_logging_spec.rb
|
240
290
|
- spec/active_record/user_brute_force_protection_spec.rb
|
291
|
+
- spec/active_record/user_magic_login_spec.rb
|
241
292
|
- spec/active_record/user_oauth_spec.rb
|
242
293
|
- spec/active_record/user_remember_me_spec.rb
|
243
294
|
- spec/active_record/user_reset_password_spec.rb
|
@@ -251,9 +302,14 @@ files:
|
|
251
302
|
- spec/controllers/controller_session_timeout_spec.rb
|
252
303
|
- spec/controllers/controller_spec.rb
|
253
304
|
- spec/orm/active_record.rb
|
305
|
+
- spec/providers/example_provider_spec.rb
|
306
|
+
- spec/providers/example_spec.rb
|
307
|
+
- spec/providers/vk_spec.rb
|
254
308
|
- spec/rails_app/app/active_record/authentication.rb
|
255
309
|
- spec/rails_app/app/active_record/user.rb
|
256
310
|
- spec/rails_app/app/active_record/user_provider.rb
|
311
|
+
- spec/rails_app/app/assets/config/manifest.js
|
312
|
+
- spec/rails_app/app/controllers/application_controller.rb
|
257
313
|
- spec/rails_app/app/controllers/sorcery_controller.rb
|
258
314
|
- spec/rails_app/app/helpers/application_helper.rb
|
259
315
|
- spec/rails_app/app/mailers/sorcery_mailer.rb
|
@@ -264,6 +320,8 @@ files:
|
|
264
320
|
- spec/rails_app/app/views/sorcery_mailer/activation_needed_email.html.erb
|
265
321
|
- spec/rails_app/app/views/sorcery_mailer/activation_success_email.html.erb
|
266
322
|
- spec/rails_app/app/views/sorcery_mailer/activation_success_email.text.erb
|
323
|
+
- spec/rails_app/app/views/sorcery_mailer/magic_login_email.html.erb
|
324
|
+
- spec/rails_app/app/views/sorcery_mailer/magic_login_email.text.erb
|
267
325
|
- spec/rails_app/app/views/sorcery_mailer/reset_password_email.html.erb
|
268
326
|
- spec/rails_app/app/views/sorcery_mailer/reset_password_email.text.erb
|
269
327
|
- spec/rails_app/app/views/sorcery_mailer/send_unlock_token_email.text.erb
|
@@ -277,15 +335,17 @@ files:
|
|
277
335
|
- spec/rails_app/config/initializers/compatible_legacy_migration.rb
|
278
336
|
- spec/rails_app/config/initializers/inflections.rb
|
279
337
|
- spec/rails_app/config/initializers/mime_types.rb
|
280
|
-
- spec/rails_app/config/initializers/secret_token.rb
|
281
338
|
- spec/rails_app/config/initializers/session_store.rb
|
282
339
|
- spec/rails_app/config/locales/en.yml
|
283
340
|
- spec/rails_app/config/routes.rb
|
341
|
+
- spec/rails_app/config/secrets.yml
|
284
342
|
- spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb
|
285
343
|
- spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb
|
286
344
|
- spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb
|
287
345
|
- spec/rails_app/db/migrate/core/20101224223620_create_users.rb
|
288
346
|
- spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb
|
347
|
+
- spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb
|
348
|
+
- spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb
|
289
349
|
- spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb
|
290
350
|
- spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb
|
291
351
|
- spec/rails_app/db/schema.rb
|
@@ -293,13 +353,18 @@ files:
|
|
293
353
|
- spec/shared_examples/user_activation_shared_examples.rb
|
294
354
|
- spec/shared_examples/user_activity_logging_shared_examples.rb
|
295
355
|
- spec/shared_examples/user_brute_force_protection_shared_examples.rb
|
356
|
+
- spec/shared_examples/user_magic_login_shared_examples.rb
|
296
357
|
- spec/shared_examples/user_oauth_shared_examples.rb
|
297
358
|
- spec/shared_examples/user_remember_me_shared_examples.rb
|
298
359
|
- spec/shared_examples/user_reset_password_shared_examples.rb
|
299
360
|
- spec/shared_examples/user_shared_examples.rb
|
300
361
|
- spec/sorcery_crypto_providers_spec.rb
|
362
|
+
- spec/sorcery_temporary_token_spec.rb
|
301
363
|
- spec/spec.opts
|
302
364
|
- spec/spec_helper.rb
|
365
|
+
- spec/support/migration_helper.rb
|
366
|
+
- spec/support/providers/example.rb
|
367
|
+
- spec/support/providers/example_provider.rb
|
303
368
|
homepage: https://github.com/Sorcery/sorcery
|
304
369
|
licenses:
|
305
370
|
- MIT
|
@@ -314,17 +379,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
314
379
|
requirements:
|
315
380
|
- - ">="
|
316
381
|
- !ruby/object:Gem::Version
|
317
|
-
version: 2.
|
382
|
+
version: 2.4.9
|
318
383
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
319
384
|
requirements:
|
320
385
|
- - ">="
|
321
386
|
- !ruby/object:Gem::Version
|
322
387
|
version: '0'
|
323
388
|
requirements: []
|
324
|
-
|
325
|
-
rubygems_version: 2.6.8
|
389
|
+
rubygems_version: 3.1.2
|
326
390
|
signing_key:
|
327
391
|
specification_version: 4
|
328
392
|
summary: Magical authentication for Rails applications
|
329
393
|
test_files: []
|
330
|
-
has_rdoc:
|