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/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/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 d4fb1eb8e..e7baee6c1 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.11.0", 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/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', ]); 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é ?", 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')