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],
+]);