From 9832b210e286788203ce03d92c67f28a82daae35 Mon Sep 17 00:00:00 2001 From: Heyang Gong Date: Tue, 10 Mar 2026 08:16:02 +0800 Subject: [PATCH 1/3] feat: OAuth independent registration (#8042) - Add oauth_registration_enabled setting to allow OAuth users to register even when general registration is disabled - Add oauth_only setting to restrict users to OAuth-only authentication - Add oauth_only field to users table to mark OAuth-only users - Update OauthController to respect new settings - Add UI controls in Advanced settings for admin configuration Closes #8042 --- app/Http/Controllers/OauthController.php | 4 ++- app/Livewire/Settings/Advanced.php | 12 ++++++++ app/Models/User.php | 1 + ...080000_add_oauth_registration_settings.php | 29 +++++++++++++++++++ ...5_03_10_080001_add_oauth_only_to_users.php | 28 ++++++++++++++++++ .../livewire/settings/advanced.blade.php | 13 ++++++++- 6 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 database/migrations/2025_03_10_080000_add_oauth_registration_settings.php create mode 100644 database/migrations/2025_03_10_080001_add_oauth_only_to_users.php diff --git a/app/Http/Controllers/OauthController.php b/app/Http/Controllers/OauthController.php index 3a3f18c9c..442a1a7e3 100644 --- a/app/Http/Controllers/OauthController.php +++ b/app/Http/Controllers/OauthController.php @@ -22,13 +22,15 @@ class OauthController extends Controller $user = User::whereEmail($oauthUser->email)->first(); if (! $user) { $settings = instanceSettings(); - if (! $settings->is_registration_enabled) { + // Allow OAuth registration if either general registration OR OAuth-specific registration is enabled + if (! $settings->is_registration_enabled && ! $settings->oauth_registration_enabled) { abort(403, 'Registration is disabled'); } $user = User::create([ 'name' => $oauthUser->name, 'email' => $oauthUser->email, + 'oauth_only' => $settings->oauth_only, ]); } Auth::login($user); diff --git a/app/Livewire/Settings/Advanced.php b/app/Livewire/Settings/Advanced.php index ad478273f..f6c125fad 100644 --- a/app/Livewire/Settings/Advanced.php +++ b/app/Livewire/Settings/Advanced.php @@ -14,6 +14,12 @@ class Advanced extends Component #[Validate('boolean')] public bool $is_registration_enabled; + #[Validate('boolean')] + public bool $oauth_registration_enabled; + + #[Validate('boolean')] + public bool $oauth_only; + #[Validate('boolean')] public bool $do_not_track; @@ -41,6 +47,8 @@ class Advanced extends Component { return [ 'is_registration_enabled' => 'boolean', + 'oauth_registration_enabled' => 'boolean', + 'oauth_only' => 'boolean', 'do_not_track' => 'boolean', 'is_dns_validation_enabled' => 'boolean', 'custom_dns_servers' => 'nullable|string', @@ -62,6 +70,8 @@ class Advanced extends Component $this->allowed_ips = $this->settings->allowed_ips; $this->do_not_track = $this->settings->do_not_track; $this->is_registration_enabled = $this->settings->is_registration_enabled; + $this->oauth_registration_enabled = $this->settings->oauth_registration_enabled ?? false; + $this->oauth_only = $this->settings->oauth_only ?? false; $this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled; $this->is_api_enabled = $this->settings->is_api_enabled; $this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation; @@ -142,6 +152,8 @@ class Advanced extends Component { try { $this->settings->is_registration_enabled = $this->is_registration_enabled; + $this->settings->oauth_registration_enabled = $this->oauth_registration_enabled; + $this->settings->oauth_only = $this->oauth_only; $this->settings->do_not_track = $this->do_not_track; $this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled; $this->settings->custom_dns_servers = $this->custom_dns_servers; diff --git a/app/Models/User.php b/app/Models/User.php index 4561cddb2..7e7100a91 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -55,6 +55,7 @@ class User extends Authenticatable implements SendsEmail 'force_password_reset' => 'boolean', 'show_boarding' => 'boolean', 'email_change_code_expires_at' => 'datetime', + 'oauth_only' => 'boolean', ]; /** diff --git a/database/migrations/2025_03_10_080000_add_oauth_registration_settings.php b/database/migrations/2025_03_10_080000_add_oauth_registration_settings.php new file mode 100644 index 000000000..bac43778f --- /dev/null +++ b/database/migrations/2025_03_10_080000_add_oauth_registration_settings.php @@ -0,0 +1,29 @@ +boolean('oauth_registration_enabled')->default(false)->after('is_registration_enabled'); + $table->boolean('oauth_only')->default(false)->after('oauth_registration_enabled'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('instance_settings', function (Blueprint $table) { + $table->dropColumn(['oauth_registration_enabled', 'oauth_only']); + }); + } +}; diff --git a/database/migrations/2025_03_10_080001_add_oauth_only_to_users.php b/database/migrations/2025_03_10_080001_add_oauth_only_to_users.php new file mode 100644 index 000000000..524e7b096 --- /dev/null +++ b/database/migrations/2025_03_10_080001_add_oauth_only_to_users.php @@ -0,0 +1,28 @@ +boolean('oauth_only')->default(false)->after('password'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('oauth_only'); + }); + } +}; diff --git a/resources/views/livewire/settings/advanced.blade.php b/resources/views/livewire/settings/advanced.blade.php index 3069c8479..5e83606cf 100644 --- a/resources/views/livewire/settings/advanced.blade.php +++ b/resources/views/livewire/settings/advanced.blade.php @@ -21,6 +21,17 @@ helper="Allow users to self-register. If disabled, only administrators can create accounts." label="Registration Allowed" /> +

OAuth Settings

+
+ +
+
+ +
- \ No newline at end of file + From 1ad047fb6bb4243efdb766a736099e03becd92d9 Mon Sep 17 00:00:00 2001 From: Heyang Gong Date: Tue, 10 Mar 2026 08:17:33 +0800 Subject: [PATCH 2/3] fix: OAuth-only enforcement and migration dates - Fix migration dates from 2025 to 2026 - Add OAuth-only enforcement in Fortify authentication - Prevent OAuth-only users from resetting passwords - Prevent OAuth-only users from updating passwords --- app/Actions/Fortify/ResetUserPassword.php | 5 +++++ app/Actions/Fortify/UpdateUserPassword.php | 5 +++++ app/Providers/FortifyServiceProvider.php | 5 +++++ ...=> 2026_03_10_080000_add_oauth_registration_settings.php} | 0 ...ers.php => 2026_03_10_080001_add_oauth_only_to_users.php} | 0 5 files changed, 15 insertions(+) rename database/migrations/{2025_03_10_080000_add_oauth_registration_settings.php => 2026_03_10_080000_add_oauth_registration_settings.php} (100%) rename database/migrations/{2025_03_10_080001_add_oauth_only_to_users.php => 2026_03_10_080001_add_oauth_only_to_users.php} (100%) diff --git a/app/Actions/Fortify/ResetUserPassword.php b/app/Actions/Fortify/ResetUserPassword.php index 158996c90..cc28b3036 100644 --- a/app/Actions/Fortify/ResetUserPassword.php +++ b/app/Actions/Fortify/ResetUserPassword.php @@ -17,6 +17,11 @@ class ResetUserPassword implements ResetsUserPasswords */ public function reset(User $user, array $input): void { + // Prevent OAuth-only users from resetting passwords + if ($user->oauth_only) { + throw new \Exception('OAuth-only users cannot reset passwords.'); + } + Validator::make($input, [ 'password' => ['required', Password::defaults(), 'confirmed'], ])->validate(); diff --git a/app/Actions/Fortify/UpdateUserPassword.php b/app/Actions/Fortify/UpdateUserPassword.php index 0c51ec56d..2b3f90207 100644 --- a/app/Actions/Fortify/UpdateUserPassword.php +++ b/app/Actions/Fortify/UpdateUserPassword.php @@ -17,6 +17,11 @@ class UpdateUserPassword implements UpdatesUserPasswords */ public function update(User $user, array $input): void { + // Prevent OAuth-only users from updating passwords + if ($user->oauth_only) { + throw new \Exception('OAuth-only users cannot update passwords.'); + } + Validator::make($input, [ 'current_password' => ['required', 'string', 'current_password:web'], 'password' => ['required', Password::defaults(), 'confirmed'], diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index 85f38b967..c062fbee3 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -78,6 +78,11 @@ class FortifyServiceProvider extends ServiceProvider $user && Hash::check($request->password, $user->password) ) { + // Prevent OAuth-only users from logging in with password + if ($user->oauth_only) { + return null; + } + $user->updated_at = now(); $user->save(); diff --git a/database/migrations/2025_03_10_080000_add_oauth_registration_settings.php b/database/migrations/2026_03_10_080000_add_oauth_registration_settings.php similarity index 100% rename from database/migrations/2025_03_10_080000_add_oauth_registration_settings.php rename to database/migrations/2026_03_10_080000_add_oauth_registration_settings.php diff --git a/database/migrations/2025_03_10_080001_add_oauth_only_to_users.php b/database/migrations/2026_03_10_080001_add_oauth_only_to_users.php similarity index 100% rename from database/migrations/2025_03_10_080001_add_oauth_only_to_users.php rename to database/migrations/2026_03_10_080001_add_oauth_only_to_users.php From 058ec42699669c276efee9734162077ca4abf5ea Mon Sep 17 00:00:00 2001 From: Heyang Gong Date: Tue, 10 Mar 2026 08:42:36 +0800 Subject: [PATCH 3/3] fix(auth): enforce global oauth_only and return validation errors instead of exceptions - Add global instanceSettings()->oauth_only check in FortifyServiceProvider - ResetUserPassword: Use ValidationException instead of Exception, add global check - UpdateUserPassword: Use ValidationException instead of Exception, add global check --- app/Actions/Fortify/ResetUserPassword.php | 8 ++++++-- app/Actions/Fortify/UpdateUserPassword.php | 8 ++++++-- app/Providers/FortifyServiceProvider.php | 5 +++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/Actions/Fortify/ResetUserPassword.php b/app/Actions/Fortify/ResetUserPassword.php index cc28b3036..a5d9e56c2 100644 --- a/app/Actions/Fortify/ResetUserPassword.php +++ b/app/Actions/Fortify/ResetUserPassword.php @@ -6,6 +6,7 @@ use App\Models\User; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rules\Password; +use Illuminate\Validation\ValidationException; use Laravel\Fortify\Contracts\ResetsUserPasswords; class ResetUserPassword implements ResetsUserPasswords @@ -17,9 +18,12 @@ class ResetUserPassword implements ResetsUserPasswords */ public function reset(User $user, array $input): void { + $settings = instanceSettings(); // Prevent OAuth-only users from resetting passwords - if ($user->oauth_only) { - throw new \Exception('OAuth-only users cannot reset passwords.'); + if ($settings->oauth_only || $user->oauth_only) { + throw ValidationException::withMessages([ + 'email' => __('Password reset is disabled for OAuth-only accounts.'), + ]); } Validator::make($input, [ diff --git a/app/Actions/Fortify/UpdateUserPassword.php b/app/Actions/Fortify/UpdateUserPassword.php index 2b3f90207..b00dab5c0 100644 --- a/app/Actions/Fortify/UpdateUserPassword.php +++ b/app/Actions/Fortify/UpdateUserPassword.php @@ -6,6 +6,7 @@ use App\Models\User; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rules\Password; +use Illuminate\Validation\ValidationException; use Laravel\Fortify\Contracts\UpdatesUserPasswords; class UpdateUserPassword implements UpdatesUserPasswords @@ -17,9 +18,12 @@ class UpdateUserPassword implements UpdatesUserPasswords */ public function update(User $user, array $input): void { + $settings = instanceSettings(); // Prevent OAuth-only users from updating passwords - if ($user->oauth_only) { - throw new \Exception('OAuth-only users cannot update passwords.'); + if ($settings->oauth_only || $user->oauth_only) { + throw ValidationException::withMessages([ + 'current_password' => __('Password update is disabled for OAuth-only accounts.'), + ]); } Validator::make($input, [ diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index c062fbee3..a63e69503 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -78,6 +78,11 @@ class FortifyServiceProvider extends ServiceProvider $user && Hash::check($request->password, $user->password) ) { + $settings = instanceSettings(); + // Prevent password login when global OAuth-only is enabled + if ($settings->oauth_only) { + return null; + } // Prevent OAuth-only users from logging in with password if ($user->oauth_only) { return null;