tesda / keycloak-auth
Keycloak SSO OpenID Connect integration for Laravel applications.
Requires
- php: ^8.2
- laravel/framework: ^10.0 || ^11.0 || ^12.0 || ^13.0
- laravel/socialite: ^5.16
- socialiteproviders/keycloak: ^4.0
Requires (Dev)
- orchestra/testbench: ^8.0 || ^9.0 || ^10.0
- phpunit/phpunit: ^10.0 || ^11.0
This package is auto-updated.
Last update: 2026-07-02 01:43:06 UTC
README
A reusable Laravel package wrapping Socialite and the Keycloak provider to enable quick, standard OpenID Connect (OIDC) Single Sign-On (SSO) integration with Keycloak (such as sso-tesda).
Features
- Zero-Config Socialite Binding: Automatically registers the Keycloak Socialite provider.
- Pre-configured Endpoints: Dynamic routes for redirect, callback, and logout (
/login/keycloak,/login/keycloak/callback,/logout/keycloak). - Flexible User Mapping: Customizable JIT provisioning and user matching by
keycloak_id(OIDCsub). - Post-Login Hook: Support for custom role/permission syncing (e.g., Spatie roles).
- Global Single Logout: Clean front-channel/back-channel global logout with
id_token_hinthandling (bypasses Keycloak logout confirmation). - Laravel 10 / 11 / 12 / 13 Compatibility: Supports PHP 8.2+ and all recent Laravel frameworks.
Installation
1. Install via Composer
Once published to Packagist, you can install the package via:
composer require tesda/keycloak-auth
For local development/testing before publishing, configure the package as a path repository in your application's composer.json:
"repositories": [ { "type": "path", "url": "../keycloak-auth" } ]
Then run:
composer require tesda/keycloak-auth:@dev
2. Publish Configuration & Migrations
Publish the package configuration and database migration:
php artisan vendor:publish --provider="Tesda\KeycloakAuth\KeycloakAuthServiceProvider"
Run the migration to add the keycloak_id column to the users table:
php artisan migrate
Configuration
In your .env file, configure the following values:
KEYCLOAK_BASE_URL=http://localhost:8080 KEYCLOAK_REALM=tesda KEYCLOAK_CLIENT_ID=your-app-client-id KEYCLOAK_CLIENT_SECRET=your-app-client-secret KEYCLOAK_REDIRECT_URI=http://your-app.test/login/keycloak/callback KEYCLOAK_LOGIN_REDIRECT=/dashboard KEYCLOAK_LOGOUT_REDIRECT=/
Customization
Custom User Mapping
By default, the package maps the Keycloak user attributes to the local User model by searching for keycloak_id, linking by email if found without keycloak_id, or creating a new user JIT.
To customize this behavior:
- Create a mapper class implementing
Tesda\KeycloakAuth\Contracts\UserMapper:
namespace App\Services; use Tesda\KeycloakAuth\Contracts\UserMapper; use Laravel\Socialite\Contracts\User as SocialiteUser; class CustomUserMapper implements UserMapper { public function map(SocialiteUser $socialiteUser, string $userModelClass) { // Custom logic to find, link or create your user... return $user; } }
- Reference your class in
config/keycloak-auth.php:
'user_mapper' => \App\Services\CustomUserMapper::class,
Authorization Gate (restrict login to specific roles)
By default any user who authenticates with Keycloak is provisioned and logged in.
To restrict an application to holders of specific realm roles (e.g. an admin
console), set required_roles. A user must hold at least one of the listed
roles or they are denied — no local account is created and no session is started.
// config/keycloak-auth.php 'required_roles' => ['system-admin'], // empty = no gate (default) 'unauthorized_redirect' => '/denied', // where denied users are sent
Or via .env:
KEYCLOAK_REQUIRED_ROLES=system-admin # comma-separated for multiple KEYCLOAK_UNAUTHORIZED_REDIRECT=/denied
The gate runs on the callback, before user mapping/login, and reads the
realm_access.roles claim from the token.
Role Synchronization
To sync roles (e.g. Spatie roles) upon successful login:
- Create a syncer class implementing
Tesda\KeycloakAuth\Contracts\RoleSyncer:
namespace App\Services; use Tesda\KeycloakAuth\Contracts\RoleSyncer; use Laravel\Socialite\Contracts\User as SocialiteUser; class CustomRoleSyncer implements RoleSyncer { public function sync($localUser, SocialiteUser $socialiteUser): void { // Extract roles from claims $roles = data_get($socialiteUser->user, 'realm_access.roles', []); // Sync to Spatie $localUser->syncRoles($roles); } }
- Reference your class in
config/keycloak-auth.php:
'role_syncer' => \App\Services\CustomRoleSyncer::class,
Routes
If register_routes is set to true in config/keycloak-auth.php (default), the following routes are registered:
- Login Redirect:
/login/keycloak(Name:keycloak.login) - Login Callback:
/login/keycloak/callback(Name:keycloak.callback) - SSO Logout:
/logout/keycloak(Name:keycloak.logout) [AcceptsGETandPOST]
License
This package is open-source software licensed under the MIT license.