From 5b1fcd6e137a67e8bc8edcada16f1efa1da70788 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 2 Oct 2026 16:45:33 +0200 Subject: [PATCH] feat(auth): show OAuth-only registration notice on login page Move the user creation check from OauthLoginService into OauthSetting::allowsUserCreation(), so the login view can use it. The login view now gets a can_register_with_oauth flag. The flag is true when an enabled OAuth provider allows creating new users. The view uses it to show the new auth.register_with_oauth message. Add translations for the message in all locales, plus test coverage. --- app/Models/OauthSetting.php | 13 +++++++++++++ app/Providers/FortifyServiceProvider.php | 3 +++ app/Services/Auth/OauthLoginService.php | 17 ++--------------- lang/ar.json | 1 + lang/az.json | 1 + lang/cs.json | 1 + lang/de.json | 1 + lang/en.json | 1 + lang/es.json | 1 + lang/fa.json | 1 + lang/fr.json | 1 + lang/id.json | 1 + lang/it.json | 1 + lang/ja.json | 1 + lang/no.json | 1 + lang/pl.json | 1 + lang/pt-br.json | 1 + lang/pt.json | 1 + lang/ro.json | 1 + lang/tr.json | 1 + lang/vi.json | 1 + lang/zh-cn.json | 1 + lang/zh-tw.json | 1 + resources/views/auth/login.blade.php | 2 ++ tests/Feature/OauthControllerTest.php | 15 +++++++++++++++ 25 files changed, 55 insertions(+), 15 deletions(-) diff --git a/app/Models/OauthSetting.php b/app/Models/OauthSetting.php index 7765e41160..4535624051 100644 --- a/app/Models/OauthSetting.php +++ b/app/Models/OauthSetting.php @@ -37,6 +37,19 @@ class OauthSetting extends Model ); } + /** + * Only OIDC exposes a provider-level user creation setting. Other providers + * follow the instance registration setting, as before OIDC support. + */ + public function allowsUserCreation(): bool + { + if (instanceSettings()->is_registration_enabled) { + return true; + } + + return $this->provider === 'oidc' && $this->allow_registration; + } + public function couldBeEnabled(): bool { switch ($this->provider) { diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index a340c2033b..70e2ed6fd6 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -65,6 +65,9 @@ class FortifyServiceProvider extends ServiceProvider return view('auth.login', [ 'is_registration_enabled' => $settings->isPasswordRegistrationAllowed(), + 'can_register_with_oauth' => $enabled_oauth_providers->contains( + fn (OauthSetting $oauthSetting) => $oauthSetting->couldBeEnabled() && $oauthSetting->allowsUserCreation() + ), 'enabled_oauth_providers' => $enabled_oauth_providers, ]); }); diff --git a/app/Services/Auth/OauthLoginService.php b/app/Services/Auth/OauthLoginService.php index 25b4f0ae82..c63bc15353 100644 --- a/app/Services/Auth/OauthLoginService.php +++ b/app/Services/Auth/OauthLoginService.php @@ -147,7 +147,7 @@ class OauthLoginService } if (! $user) { - if (! $this->canCreateUser($oauthSetting)) { + if (! $oauthSetting->allowsUserCreation()) { throw new OauthLoginException('Registration is disabled', 'auth.registration_disabled'); } @@ -266,7 +266,7 @@ class OauthLoginService } if (! $user) { - if (! $this->canCreateUser($oauthSetting)) { + if (! $oauthSetting->allowsUserCreation()) { throw new OauthLoginException('Registration is disabled', 'auth.registration_disabled'); } @@ -290,19 +290,6 @@ class OauthLoginService } } - /** - * Only OIDC exposes a provider-level user creation setting. Other providers - * follow the instance registration setting, as before OIDC support. - */ - private function canCreateUser(OauthSetting $oauthSetting): bool - { - if (instanceSettings()->is_registration_enabled) { - return true; - } - - return $oauthSetting->provider === 'oidc' && $oauthSetting->allow_registration; - } - private function createUser(string $name, string $email, OauthSetting $oauthSetting): User { if (User::count() === 0) { diff --git a/lang/ar.json b/lang/ar.json index c3aa8aa18d..d12f9a54ea 100644 --- a/lang/ar.json +++ b/lang/ar.json @@ -18,6 +18,7 @@ "auth.logout": "تسجيل الخروج", "auth.register": "تسجيل", "auth.registration_disabled": "تم تعطيل التسجيل. يرجى التواصل مع المسؤول.", + "auth.register_with_oauth": "التسجيل متاح فقط عبر OAuth.", "auth.reset_password": "إعادة تعيين كلمة المرور", "auth.failed": "هذه البيانات لا تتطابق مع سجلاتنا.", "auth.failed.callback": "فشل في معالجة استدعاء من مزود تسجيل الدخول.", diff --git a/lang/az.json b/lang/az.json index 9ac7a03b0e..6e99979d75 100644 --- a/lang/az.json +++ b/lang/az.json @@ -18,6 +18,7 @@ "auth.logout": "Çıxış", "auth.register": "Qeydiyyat", "auth.registration_disabled": "Qeydiyyat bağlıdır. Administratorla əlaqə saxlayın.", + "auth.register_with_oauth": "Yalnız OAuth ilə qeydiyyat aktivdir.", "auth.reset_password": "Şifrənin bərpası", "auth.failed": "Bu məlumatlar bizim qeydlərimizlə uyğun gəlmir.", "auth.failed.callback": "Giriş təminatçısından geri çağırma işlənə bilmədi.", diff --git a/lang/cs.json b/lang/cs.json index b4bddfba4f..e1e8be0d68 100644 --- a/lang/cs.json +++ b/lang/cs.json @@ -17,6 +17,7 @@ "auth.logout": "Odhlásit se", "auth.register": "Registrovat se", "auth.registration_disabled": "Registrace je zakázána. Kontaktujte prosím administrátora.", + "auth.register_with_oauth": "Je povolena pouze registrace přes OAuth.", "auth.reset_password": "Obnovit heslo", "auth.failed": "Tyto údaje neodpovídají našim záznamům.", "auth.failed.callback": "Nepodařilo se zpracovat zpětné volání od poskytovatele přihlášení.", diff --git a/lang/de.json b/lang/de.json index 6e354c7cc5..5c6e385ab4 100644 --- a/lang/de.json +++ b/lang/de.json @@ -19,6 +19,7 @@ "auth.logout": "Abmelden", "auth.register": "Registrieren", "auth.registration_disabled": "Registrierung ist deaktiviert. Bitte kontaktiere einen Administrator.", + "auth.register_with_oauth": "Nur die Registrierung über OAuth ist aktiviert.", "auth.reset_password": "Passwort zurücksetzen", "auth.failed": "Diese Anmeldedaten wurden nicht gefunden.", "auth.failed.callback": "Fehlerhafte Verarbeitung der Antwort des Anmeldeanbieters.", diff --git a/lang/en.json b/lang/en.json index f9d1bfc9ec..d840d749a4 100644 --- a/lang/en.json +++ b/lang/en.json @@ -21,6 +21,7 @@ "auth.logout": "Logout", "auth.register": "Register", "auth.registration_disabled": "Registration is disabled. Please contact the administrator.", + "auth.register_with_oauth": "Only OAuth registration is enabled.", "auth.reset_password": "Reset password", "auth.failed": "These credentials do not match our records.", "auth.failed.callback": "Failed to process callback from login provider.", diff --git a/lang/es.json b/lang/es.json index 732e1bf794..ff7f623933 100644 --- a/lang/es.json +++ b/lang/es.json @@ -17,6 +17,7 @@ "auth.logout": "Cerrar sesión", "auth.register": "Registrar", "auth.registration_disabled": "El registro está desactivado. Por favor contacta con el administrador.", + "auth.register_with_oauth": "Solo está habilitado el registro mediante OAuth.", "auth.reset_password": "Cambiar contraseña", "auth.failed": "Las credenciales no coinciden con nuestro registro..", "auth.failed.callback": "Falló el proceso de inicio de sesión con el proveedor.", diff --git a/lang/fa.json b/lang/fa.json index 943dbb7c61..6fd2c1ee2e 100644 --- a/lang/fa.json +++ b/lang/fa.json @@ -17,6 +17,7 @@ "auth.logout": "خروج", "auth.register": "ثبت نام", "auth.registration_disabled": "ثبت نام غیر فعال است. لطفا با ادمین تماس بگیرید.", + "auth.register_with_oauth": "فقط ثبت‌نام از طریق OAuth فعال است.", "auth.reset_password": "بازیابی رمز عبور", "auth.failed": "این اطلاعات با سوابق ما مطابقت ندارد.", "auth.failed.callback": "پردازش بازگشت از ارائه‌دهنده ورود با شکست مواجه شد.", diff --git a/lang/fr.json b/lang/fr.json index 07ccebd68c..e4912ee7b2 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -18,6 +18,7 @@ "auth.logout": "Déconnexion", "auth.register": "S'enregistrer", "auth.registration_disabled": "L'enregistrement est désactivé. Merci de contacter l'administrateur.", + "auth.register_with_oauth": "Seule l'inscription via OAuth est activée.", "auth.reset_password": "Réinitialiser le mot de passe", "auth.failed": "Aucune correspondance n'a été trouvée pour les informations d'identification renseignées.", "auth.failed.callback": "Erreur lors du processus de retour de la plateforme de connexion.", diff --git a/lang/id.json b/lang/id.json index 0ff9b13508..33dde7d83a 100644 --- a/lang/id.json +++ b/lang/id.json @@ -18,6 +18,7 @@ "auth.logout": "Keluar", "auth.register": "Daftar", "auth.registration_disabled": "Pendaftaran dinonaktifkan. Harap hubungi administrator.", + "auth.register_with_oauth": "Hanya pendaftaran melalui OAuth yang diaktifkan.", "auth.reset_password": "Reset kata sandi", "auth.failed": "Kredensial ini tidak cocok dengan catatan kami.", "auth.failed.callback": "Gagal memproses callback dari penyedia login.", diff --git a/lang/it.json b/lang/it.json index 1904fdcada..9f3659b954 100644 --- a/lang/it.json +++ b/lang/it.json @@ -18,6 +18,7 @@ "auth.logout": "Esci", "auth.register": "Registrati", "auth.registration_disabled": "La registrazione è disabilitata. Si prega di contattare l'amministratore.", + "auth.register_with_oauth": "È abilitata solo la registrazione tramite OAuth.", "auth.reset_password": "Reimposta password", "auth.failed": "Queste credenziali non corrispondono ai nostri record.", "auth.failed.callback": "Errore durante l'elaborazione del callback dal provider di accesso.", diff --git a/lang/ja.json b/lang/ja.json index 67b0395066..6ca2acf6d8 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -17,6 +17,7 @@ "auth.logout": "ログアウト", "auth.register": "登録", "auth.registration_disabled": "登録は無効です。管理者に連絡してください。", + "auth.register_with_oauth": "OAuth による登録のみ有効です。", "auth.reset_password": "パスワードをリセット", "auth.failed": "これらの資格情報は記録と一致しません。", "auth.failed.callback": "ログインプロバイダーからのコールバックの処理に失敗しました。", diff --git a/lang/no.json b/lang/no.json index 707229c9cf..b5cb5f193d 100644 --- a/lang/no.json +++ b/lang/no.json @@ -18,6 +18,7 @@ "auth.logout": "Logg ut", "auth.register": "Registrer", "auth.registration_disabled": "Registrering er deaktivert. Vennligst kontakt administrator.", + "auth.register_with_oauth": "Bare registrering via OAuth er aktivert.", "auth.reset_password": "Tilbakestill passord", "auth.failed": "Disse legitimasjonene samsvarer ikke med våre registre.", "auth.failed.callback": "Klarte ikke å behandle tilbakekall fra innloggingsleverandør.", diff --git a/lang/pl.json b/lang/pl.json index d5b55cd671..f8d7d1df78 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -20,6 +20,7 @@ "auth.logout": "Wyloguj", "auth.register": "Zarejestruj", "auth.registration_disabled": "Rejestracja jest wyłączona. Skontaktuj się z administratorem.", + "auth.register_with_oauth": "Włączona jest tylko rejestracja przez OAuth.", "auth.reset_password": "Zresetuj hasło", "auth.failed": "Podane dane nie zgadzają się z naszymi rekordami.", "auth.failed.callback": "Nie udało się przeprocesować callbacku od dostawcy logowania.", diff --git a/lang/pt-br.json b/lang/pt-br.json index aaa01c536e..ea50efc5d2 100644 --- a/lang/pt-br.json +++ b/lang/pt-br.json @@ -19,6 +19,7 @@ "auth.logout": "Sair", "auth.register": "Cadastrar", "auth.registration_disabled": "O registro está desativado. Por favor, contate o administrador.", + "auth.register_with_oauth": "Apenas o cadastro via OAuth está habilitado.", "auth.reset_password": "Redefinir senha", "auth.failed": "Essas credenciais não correspondem aos nossos registros.", "auth.failed.callback": "Falha ao processar o callback do provedor de login.", diff --git a/lang/pt.json b/lang/pt.json index a5dc8b820f..34a8419b92 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -19,6 +19,7 @@ "auth.logout": "Sair", "auth.register": "Cadastrar", "auth.registration_disabled": "Cadastro desativado. Por favor, entre em contato com o administrador.", + "auth.register_with_oauth": "Apenas o registo através de OAuth está ativado.", "auth.reset_password": "Redefinir senha", "auth.failed": "Essas credenciais não correspondem aos nossos registros.", "auth.failed.callback": "Falha ao processar o callback do provedor de login.", diff --git a/lang/ro.json b/lang/ro.json index addce9b712..a578800266 100644 --- a/lang/ro.json +++ b/lang/ro.json @@ -17,6 +17,7 @@ "auth.logout": "Deconectare", "auth.register": "Înregistrare", "auth.registration_disabled": "Înregistrarea este dezactivată. Vă rugăm să contactați administratorul site-ului.", + "auth.register_with_oauth": "Este activată doar înregistrarea prin OAuth.", "auth.reset_password": "Resetare parolă", "auth.failed": "Autentificare nereușită. Vă rugăm să verificați datele introduse.", "auth.failed.callback": "A apărut o eroare în timpul autentificării cu furnizorul extern.", diff --git a/lang/tr.json b/lang/tr.json index ba138d6745..4d258e5355 100644 --- a/lang/tr.json +++ b/lang/tr.json @@ -19,6 +19,7 @@ "auth.logout": "Çıkış Yap", "auth.register": "Kayıt Ol", "auth.registration_disabled": "Kayıt devre dışı bırakıldı. Lütfen yöneticiyle iletişime geçin.", + "auth.register_with_oauth": "Yalnızca OAuth ile kayıt etkin.", "auth.reset_password": "Şifreyi Sıfırla", "auth.failed": "Bu kimlik bilgileri kayıtlarımızla eşleşmiyor.", "auth.failed.callback": "Giriş sağlayıcıdan gelen istek işlenemedi.", diff --git a/lang/vi.json b/lang/vi.json index a5bde607d8..c2b31fda71 100644 --- a/lang/vi.json +++ b/lang/vi.json @@ -17,6 +17,7 @@ "auth.logout": "Đăng xuất", "auth.register": "Đăng ký", "auth.registration_disabled": "Đăng ký không khả dụng. Vui lòng liên hệ quản trị viên.", + "auth.register_with_oauth": "Chỉ cho phép đăng ký qua OAuth.", "auth.reset_password": "Đặt lại mật khẩu", "auth.failed": "Thông tin đăng nhập không khớp với bất kỳ tài khoản nào.", "auth.failed.callback": "Xử lý thông tin từ nhà cung cấp đăng nhập thất bại.", diff --git a/lang/zh-cn.json b/lang/zh-cn.json index 6b531aaaa8..417ebbcf67 100644 --- a/lang/zh-cn.json +++ b/lang/zh-cn.json @@ -19,6 +19,7 @@ "auth.logout": "退出登录", "auth.register": "注册", "auth.registration_disabled": "注册已禁用,请联系管理员", + "auth.register_with_oauth": "仅启用了 OAuth 注册。", "auth.reset_password": "重置密码", "auth.failed": "这些凭据与我们的记录不符", "auth.failed.callback": "处理第三方登录的回调时出错", diff --git a/lang/zh-tw.json b/lang/zh-tw.json index 3d0606753c..461e473203 100644 --- a/lang/zh-tw.json +++ b/lang/zh-tw.json @@ -17,6 +17,7 @@ "auth.logout": "登出", "auth.register": "註冊", "auth.registration_disabled": "註冊已停用,請聯絡管理員。", + "auth.register_with_oauth": "僅啟用 OAuth 註冊。", "auth.reset_password": "重設密碼", "auth.failed": "這些憑證與我們的記錄不符。", "auth.failed.callback": "無法處理來自登入提供者的回呼。", diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 12eb57867c..476b153985 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -99,6 +99,8 @@ @if ($is_registration_enabled) New to Coolify? {{ __('auth.register_now') }} + @elseif ($can_register_with_oauth) + {{ __('auth.register_with_oauth') }} @else {{ __('auth.registration_disabled') }} @endif diff --git a/tests/Feature/OauthControllerTest.php b/tests/Feature/OauthControllerTest.php index 3f944d2941..e321f1bc7a 100644 --- a/tests/Feature/OauthControllerTest.php +++ b/tests/Feature/OauthControllerTest.php @@ -863,3 +863,18 @@ it('matches the Google hosted domain without case or spaces and accepts any Work 'other domain' => ['example.com', 'example.org', false], 'personal account' => ['example.com', null, false], ]); + +it('allows OAuth user creation through global registration or the OIDC user creation setting', function (string $provider, bool $isRegistrationEnabled, bool $allowRegistration, bool $expected) { + InstanceSettings::query()->whereKey(0)->update(['is_registration_enabled' => $isRegistrationEnabled]); + Once::flush(); + + $setting = new OauthSetting(['provider' => $provider, 'allow_registration' => $allowRegistration]); + + expect($setting->allowsUserCreation())->toBe($expected); +})->with([ + 'github, registration on' => ['github', true, false, true], + 'github, registration off' => ['github', false, true, false], + 'oidc, registration off, oidc user creation on' => ['oidc', false, true, true], + 'oidc, registration off, oidc user creation off' => ['oidc', false, false, false], + 'oidc, registration on, oidc user creation off' => ['oidc', true, false, true], +]);