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
This commit is contained in:
Heyang Gong 2026-03-10 08:16:02 +08:00
parent 5b701ebb07
commit 9832b210e2
6 changed files with 85 additions and 2 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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',
];
/**

View file

@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('instance_settings', function (Blueprint $table) {
$table->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']);
});
}
};

View file

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('oauth_only')->default(false)->after('password');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('oauth_only');
});
}
};

View file

@ -21,6 +21,17 @@
helper="Allow users to self-register. If disabled, only administrators can create accounts."
label="Registration Allowed" />
</div>
<h4 class="pt-4">OAuth Settings</h4>
<div class="md:w-96">
<x-forms.checkbox instantSave id="oauth_registration_enabled"
helper="Allow users to self-register via OAuth providers even when general registration is disabled."
label="OAuth Registration" />
</div>
<div class="md:w-96">
<x-forms.checkbox instantSave id="oauth_only"
helper="Restrict users to OAuth-only authentication. OAuth users cannot create or use passwords. This allows centralized access control via your OAuth provider."
label="OAuth Only" />
</div>
<div class="md:w-96">
<x-forms.checkbox instantSave id="do_not_track"
helper="Opt out of reporting this instance to coolify.io's installation count. No other data is collected."
@ -95,4 +106,4 @@
</div>
</form>
</div>
</div>
</div>