diff --git a/app/Http/Controllers/Auth/SocialiteController.php b/app/Http/Controllers/Auth/SocialiteController.php index 27471a86..17d70b67 100644 --- a/app/Http/Controllers/Auth/SocialiteController.php +++ b/app/Http/Controllers/Auth/SocialiteController.php @@ -57,7 +57,7 @@ public function callback(Request $request, string $driver) return redirect('/error?err=sso_email_already_used'); } elseif (User::count() === 0) { $user->promoteToAdministrator(); - } elseif (Settings::get('disableRegistration')) { + } elseif (Settings::get('disableRegistration') && ! Settings::get('keepSsoRegistrationEnabled')) { return redirect('/error?err=sso_no_register'); } $user->password = bcrypt(Str::random()); diff --git a/config/2fauth.php b/config/2fauth.php index 2f0343f9..d9fcb8f1 100644 --- a/config/2fauth.php +++ b/config/2fauth.php @@ -75,6 +75,7 @@ 'disableRegistration' => false, 'enableSso' => true, 'restrictRegistration' => false, + 'keepSsoRegistrationEnabled' => false, ], /* diff --git a/resources/js/views/admin/AppSetup.vue b/resources/js/views/admin/AppSetup.vue index d5205f3c..35c375d2 100644 --- a/resources/js/views/admin/AppSetup.vue +++ b/resources/js/views/admin/AppSetup.vue @@ -29,6 +29,7 @@ restrictList: appSettings.restrictList, restrictRule: appSettings.restrictRule, disableRegistration: appSettings.disableRegistration, + keepSsoRegistrationEnabled: appSettings.keepSsoRegistrationEnabled, enableSso: appSettings.enableSso, }) @@ -171,6 +172,8 @@

{{ $t('admin.registrations') }}

+ + @@ -179,8 +182,8 @@ - - + +

{{ $t('commons.environment') }}

diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php index 9fba60c6..8d85782e 100644 --- a/resources/lang/en/admin.php +++ b/resources/lang/en/admin.php @@ -76,7 +76,7 @@ ], 'restrict_registration' => [ 'label' => 'Restrict registration', - 'help' => 'Make registration only available to a limited range of email addresses. Both rules can be used simultaneously.', + 'help' => 'Make registration only available to a limited range of email addresses. Both rules can be used simultaneously. This has no effect on registration via SSO.', ], 'restrict_list' => [ 'label' => 'Filtering list', @@ -88,12 +88,16 @@ ], 'disable_registration' => [ 'label' => 'Disable registration', - 'help' => 'Prevent new user registration. This affects SSO as well, so new SSO users won\'t be able to sign on', + 'help' => 'Prevent new user registration. Unless overridden (see below), this affects SSO as well, so new users won\'t be able to sign in via SSO', ], 'enable_sso' => [ 'label' => 'Enable Single Sign-On (SSO)', 'help' => 'Allow visitors to authenticate using an external ID via the Single Sign-On scheme', ], + 'keep_sso_registration_enabled' => [ + 'label' => 'Keep SSO registration enabled', + 'help' => 'Allow new users to sign in for the first time via SSO whereas registration is disabled', + ], 'is_admin' => [ 'label' => 'Is administrator', 'help' => 'Give administrator rights to the user. Administrators have permissions to manage the whole app, i.e. settings and other users, but cannot generate password for a 2FA they don\'t own.' diff --git a/tests/Feature/Http/Auth/SocialiteControllerTest.php b/tests/Feature/Http/Auth/SocialiteControllerTest.php index d1ca7aef..97567ab3 100644 --- a/tests/Feature/Http/Auth/SocialiteControllerTest.php +++ b/tests/Feature/Http/Auth/SocialiteControllerTest.php @@ -253,9 +253,10 @@ public function test_callback_returns_error_when_email_is_already_used() /** * @test */ - public function test_callback_returns_error_when_registrations_are_closed() + public function test_callback_redirects_to_error_when_registrations_are_closed() { Settings::set('disableRegistration', true); + Settings::set('keepSsoRegistrationEnabled', false); $newSocialiteUser = new \Laravel\Socialite\Two\User; $newSocialiteUser->id = 'rejected_id'; @@ -273,9 +274,10 @@ public function test_callback_returns_error_when_registrations_are_closed() /** * @test */ - public function test_callback_skips_registration_when_registrations_are_closed() + public function test_callback_skips_registration_when_all_registrations_are_closed() { Settings::set('disableRegistration', true); + Settings::set('keepSsoRegistrationEnabled', false); $newSocialiteUser = new \Laravel\Socialite\Two\User; $newSocialiteUser->id = 'rejected_id'; @@ -292,4 +294,30 @@ public function test_callback_skips_registration_when_registrations_are_closed() 'oauth_provider' => self::USER_OAUTH_PROVIDER, ]); } + + /** + * @test + */ + public function test_callback_registers_new_user_when_sso_registrations_are_enabled() + { + Settings::set('disableRegistration', true); + Settings::set('keepSsoRegistrationEnabled', true); + + $newSocialiteUser = new \Laravel\Socialite\Two\User; + $newSocialiteUser->id = 'new_id'; + $newSocialiteUser->name = 'jane'; + $newSocialiteUser->email = 'jane@provider.com'; + + Socialite::shouldReceive('driver->user') + ->andReturn($newSocialiteUser); + + $response = $this->get('/socialite/callback/github', ['driver' => 'github']); + + $this->assertDatabaseHas('users', [ + 'oauth_id' => 'new_id', + 'oauth_provider' => self::USER_OAUTH_PROVIDER, + 'email' => 'jane@provider.com', + 'is_admin' => 0, + ]); + } }