From 71a85e2f68c85d57e427fbfe8c048d07f682cbdd Mon Sep 17 00:00:00 2001 From: ryzenixx Date: Fri, 6 Feb 2026 23:40:29 +0100 Subject: [PATCH 1/4] feat(auth): add keycloak oauth support --- app/Models/OauthSetting.php | 2 + bootstrap/helpers/socialite.php | 11 ++++ composer.json | 1 + composer.lock | 52 ++++++++++++++++++- config/services.php | 8 +++ ..._000000_add_keycloak_to_oauth_settings.php | 27 ++++++++++ .../views/livewire/settings-oauth.blade.php | 7 +-- 7 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 database/migrations/2025_02_07_000000_add_keycloak_to_oauth_settings.php diff --git a/app/Models/OauthSetting.php b/app/Models/OauthSetting.php index 08e08d85b..74ddebd75 100644 --- a/app/Models/OauthSetting.php +++ b/app/Models/OauthSetting.php @@ -29,6 +29,8 @@ class OauthSetting extends Model case 'authentik': case 'clerk': return filled($this->client_id) && filled($this->client_secret) && filled($this->base_url); + case 'keycloak': + return filled($this->client_id) && filled($this->client_secret) && filled($this->base_url) && filled($this->tenant); default: return filled($this->client_id) && filled($this->client_secret); } diff --git a/bootstrap/helpers/socialite.php b/bootstrap/helpers/socialite.php index fd3fbe74b..39c147bdc 100644 --- a/bootstrap/helpers/socialite.php +++ b/bootstrap/helpers/socialite.php @@ -33,6 +33,17 @@ function get_socialite_provider(string $provider) return Socialite::driver($provider)->setConfig($authentik_clerk_config); } + if ($provider == 'keycloak') { + $keycloak_config = new \SocialiteProviders\Manager\Config( + $oauth_setting->client_id, + $oauth_setting->client_secret, + $oauth_setting->redirect_uri, + ['base_url' => $oauth_setting->base_url, 'realms' => $oauth_setting->tenant], + ); + + return Socialite::driver('keycloak')->setConfig($keycloak_config); + } + if ($provider == 'zitadel') { $zitadel_config = new \SocialiteProviders\Manager\Config( $oauth_setting->client_id, diff --git a/composer.json b/composer.json index 0aeb91958..c2263a88c 100644 --- a/composer.json +++ b/composer.json @@ -43,6 +43,7 @@ "socialiteproviders/discord": "^4.2", "socialiteproviders/google": "^4.1", "socialiteproviders/infomaniak": "^4.0", + "socialiteproviders/keycloak": "^5.3", "socialiteproviders/microsoft-azure": "^5.2", "socialiteproviders/zitadel": "^4.2", "spatie/laravel-activitylog": "^4.10.2", diff --git a/composer.lock b/composer.lock index 38e2373fd..93268d11c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "710c697fd96f4388646963daf6f10304", + "content-hash": "71773b93dcde4806f9d5e261f9a6b2b5", "packages": [ { "name": "aws/aws-crt-php", @@ -6706,6 +6706,56 @@ }, "time": "2024-11-20T05:42:36+00:00" }, + { + "name": "socialiteproviders/keycloak", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/SocialiteProviders/Keycloak.git", + "reference": "87d13f8a411a6f8f5010ecbaff9aedd4494863e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SocialiteProviders/Keycloak/zipball/87d13f8a411a6f8f5010ecbaff9aedd4494863e4", + "reference": "87d13f8a411a6f8f5010ecbaff9aedd4494863e4", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.4 || ^8.0", + "socialiteproviders/manager": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "SocialiteProviders\\Keycloak\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oleg Kuchumov", + "email": "voenniy@gmail.com" + } + ], + "description": "Keycloak OAuth2 Provider for Laravel Socialite", + "keywords": [ + "keycloak", + "laravel", + "oauth", + "provider", + "socialite" + ], + "support": { + "docs": "https://socialiteproviders.com/keycloak", + "issues": "https://github.com/socialiteproviders/providers/issues", + "source": "https://github.com/socialiteproviders/providers" + }, + "time": "2023-04-10T05:50:49+00:00" + }, { "name": "socialiteproviders/manager", "version": "v4.8.1", diff --git a/config/services.php b/config/services.php index 6a21cda18..07724711d 100644 --- a/config/services.php +++ b/config/services.php @@ -67,4 +67,12 @@ return [ 'base_url' => env('ZITADEL_BASE_URL'), ], + 'keycloak' => [ + 'base_url' => env('KEYCLOAK_BASE_URL'), + 'realms' => env('KEYCLOAK_REALM', 'master'), + 'client_id' => env('KEYCLOAK_CLIENT_ID'), + 'client_secret' => env('KEYCLOAK_CLIENT_SECRET'), + 'redirect' => env('KEYCLOAK_REDIRECT_URI'), + ], + ]; diff --git a/database/migrations/2025_02_07_000000_add_keycloak_to_oauth_settings.php b/database/migrations/2025_02_07_000000_add_keycloak_to_oauth_settings.php new file mode 100644 index 000000000..035e54359 --- /dev/null +++ b/database/migrations/2025_02_07_000000_add_keycloak_to_oauth_settings.php @@ -0,0 +1,27 @@ + 'keycloak', + 'enabled' => false, + ]); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + \App\Models\OauthSetting::where('provider', 'keycloak')->delete(); + } +}; diff --git a/resources/views/livewire/settings-oauth.blade.php b/resources/views/livewire/settings-oauth.blade.php index 7650a5654..4ddce3568 100644 --- a/resources/views/livewire/settings-oauth.blade.php +++ b/resources/views/livewire/settings-oauth.blade.php @@ -32,15 +32,16 @@ @endif - @if ($oauth_setting['provider'] == 'google') + @if ($oauth_setting['provider'] == 'google' || $oauth_setting['provider'] == 'keycloak') + helper="{{ $oauth_setting['provider'] == 'google' ? 'Optional parameter that supplies a hosted domain (HD) to Google, which
triggers a login hint to be displayed on the OAuth screen with this domain.

Google Documentation' : 'The Realm name for your Keycloak instance. Default is \'master\'.' }}" + label="{{ $oauth_setting['provider'] == 'google' ? 'Tenant' : 'Realm' }}" /> @endif @if ( $oauth_setting['provider'] == 'authentik' || $oauth_setting['provider'] == 'clerk' || $oauth_setting['provider'] == 'zitadel' || + $oauth_setting['provider'] == 'keycloak' || $oauth_setting['provider'] == 'gitlab') From 0d9ece60ad19a21a31fccd9ae09e3210cce0597c Mon Sep 17 00:00:00 2001 From: ryzenixx Date: Fri, 6 Feb 2026 23:51:56 +0100 Subject: [PATCH 2/4] fix(auth): register keycloak event listener and add translations --- app/Providers/EventServiceProvider.php | 2 ++ lang/en.json | 1 + lang/fr.json | 2 ++ 3 files changed, 5 insertions(+) diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 9163d595c..3bd308bba 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -11,6 +11,7 @@ use SocialiteProviders\Google\GoogleExtendSocialite; use SocialiteProviders\Infomaniak\InfomaniakExtendSocialite; use SocialiteProviders\Manager\SocialiteWasCalled; use SocialiteProviders\Zitadel\ZitadelExtendSocialite; +use SocialiteProviders\Keycloak\KeycloakExtendSocialite; class EventServiceProvider extends ServiceProvider { @@ -23,6 +24,7 @@ class EventServiceProvider extends ServiceProvider GoogleExtendSocialite::class.'@handle', InfomaniakExtendSocialite::class.'@handle', ZitadelExtendSocialite::class.'@handle', + KeycloakExtendSocialite::class.'@handle', ], ]; diff --git a/lang/en.json b/lang/en.json index a81e1ee68..5329e0245 100644 --- a/lang/en.json +++ b/lang/en.json @@ -9,6 +9,7 @@ "auth.login.gitlab": "Login with Gitlab", "auth.login.google": "Login with Google", "auth.login.infomaniak": "Login with Infomaniak", + "auth.login.keycloak": "Login with Keycloak", "auth.login.zitadel": "Login with Zitadel", "auth.already_registered": "Already registered?", "auth.confirm_password": "Confirm password", diff --git a/lang/fr.json b/lang/fr.json index d98a1ebc8..554f689d9 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -9,6 +9,8 @@ "auth.login.gitlab": "Connexion avec Gitlab", "auth.login.google": "Connexion avec Google", "auth.login.infomaniak": "Connexion avec Infomaniak", + "auth.login.keycloak": "Connexion avec Keycloak", + "auth.login.zitadel": "Connexion avec Zitadel", "auth.already_registered": "Déjà enregistré ?", "auth.confirm_password": "Confirmer le mot de passe", "auth.forgot_password_link": "Mot de passe oublié ?", From 68458a6d74252901d4286f49a4571bc75a827cf3 Mon Sep 17 00:00:00 2001 From: ryzenixx Date: Sun, 8 Feb 2026 20:54:54 +0100 Subject: [PATCH 3/4] feat(seeder): add keycloak --- database/seeders/OauthSettingSeeder.php | 1 + 1 file changed, 1 insertion(+) diff --git a/database/seeders/OauthSettingSeeder.php b/database/seeders/OauthSettingSeeder.php index 2e5e6fcc4..f4d32c780 100644 --- a/database/seeders/OauthSettingSeeder.php +++ b/database/seeders/OauthSettingSeeder.php @@ -24,6 +24,7 @@ class OauthSettingSeeder extends Seeder 'google', 'authentik', 'infomaniak', + 'keycloak', 'zitadel', ]); From cea5024282a3ec77668893d449fa17eca75b14f4 Mon Sep 17 00:00:00 2001 From: ryzenixx Date: Mon, 9 Feb 2026 10:51:33 +0100 Subject: [PATCH 4/4] chore: revert composer.lock changes --- composer.lock | 52 +-------------------------------------------------- 1 file changed, 1 insertion(+), 51 deletions(-) diff --git a/composer.lock b/composer.lock index 93268d11c..38e2373fd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "71773b93dcde4806f9d5e261f9a6b2b5", + "content-hash": "710c697fd96f4388646963daf6f10304", "packages": [ { "name": "aws/aws-crt-php", @@ -6706,56 +6706,6 @@ }, "time": "2024-11-20T05:42:36+00:00" }, - { - "name": "socialiteproviders/keycloak", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/SocialiteProviders/Keycloak.git", - "reference": "87d13f8a411a6f8f5010ecbaff9aedd4494863e4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Keycloak/zipball/87d13f8a411a6f8f5010ecbaff9aedd4494863e4", - "reference": "87d13f8a411a6f8f5010ecbaff9aedd4494863e4", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": "^7.4 || ^8.0", - "socialiteproviders/manager": "~4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "SocialiteProviders\\Keycloak\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Oleg Kuchumov", - "email": "voenniy@gmail.com" - } - ], - "description": "Keycloak OAuth2 Provider for Laravel Socialite", - "keywords": [ - "keycloak", - "laravel", - "oauth", - "provider", - "socialite" - ], - "support": { - "docs": "https://socialiteproviders.com/keycloak", - "issues": "https://github.com/socialiteproviders/providers/issues", - "source": "https://github.com/socialiteproviders/providers" - }, - "time": "2023-04-10T05:50:49+00:00" - }, { "name": "socialiteproviders/manager", "version": "v4.8.1",