Of course, Abhishek. This is the classic use case for Single Sign-On (SSO), and Keycloak is the perfect tool for the job. You want a central user login (Keycloak) that, once authenticated, grants access to multiple, separate Laravel applications without requiring the user to log in again.
Here is a comprehensive, step-by-step guide to achieving true SSO across your Laravel projects (including Eventmie Pro) using Keycloak as the central Identity Provider (IdP).
The Core Concept: Central Authentication
The flow you want is this:
- A user visits App A (e.g., Eventmie Pro) and is not logged in.
- App A redirects them to Keycloak to log in.
- The user provides their credentials only to Keycloak.
- Keycloak confirms their identity and redirects them back to App A, now logged in.
- Later, the user opens App B (another Laravel project).
- App B, seeing no local session, also redirects to Keycloak.
- Keycloak recognizes the user already has an active SSO session and immediately redirects them back to App B, logged in, without asking for credentials again.
This works because the user has an active session with the IdP (Keycloak), and both App A and App B trust that IdP.
Part 1: Keycloak Configuration (The Central Hub)
This part is done once. You will create a “client” for each of your Laravel applications within the same Keycloak realm.
Step 1: Create a Realm
If you haven’t already, create a single realm that all your applications will share.
- Log in to your Keycloak Admin Console.
- Hover over the realm name (e.g.,
Master
) and click Add Realm. - Name it something like
my-sso-realm
and click Create.
Step 2: Create a Client for Each Laravel Application
You must repeat this step for every Laravel project you want to connect.
Let’s assume you have two apps: Eventmie Pro and “Project X”.
For Eventmie Pro:
- Go to Clients and click Create.
- Client ID:
eventmie-pro-client
- Client Protocol:
openid-connect
- Click Save.
- Settings:
- Access Type:
confidential
- Valid Redirect URIs:
https://eventmie-domain.com/auth/keycloak/callback
- Access Type:
- Go to the Credentials tab and copy the Secret. Save it for later.
For Project X:
- Go back to Clients and click Create again.
- Client ID:
project-x-client
- Client Protocol:
openid-connect
- Click Save.
- Settings:
- Access Type:
confidential
- Valid Redirect URIs:
https://project-x-domain.com/auth/keycloak/callback
- Access Type:
- Go to the Credentials tab and copy the Secret. Save this one too.
You now have Keycloak configured to recognize both applications.
Part 2: Laravel Application Configuration (The Spokes)
You must repeat the following steps for each of your Laravel applications (Eventmie Pro, Project X, etc.), using the unique client details for each one.
Step 3: Install Packages
In the terminal for each project, run:
bashcomposer require laravel/socialite socialiteproviders/keycloak
Step 4: Configure Environment (.env
file)
This is the most critical part for making each app unique.
In your Eventmie Pro .env
file:
textKEYCLOAK_BASE_URL="http://your-keycloak-server:8080"
KEYCLOAK_REALM="my-sso-realm"
KEYCLOAK_CLIENT_ID="eventmie-pro-client"
KEYCLOAK_CLIENT_SECRET="<secret-from-eventmie-client>"
KEYCLOAK_REDIRECT_URI="https://eventmie-domain.com/auth/keycloak/callback"
In your Project X .env
file:
textKEYCLOAK_BASE_URL="http://your-keycloak-server:8080"
KEYCLOAK_REALM="my-sso-realm"
KEYCLOAK_CLIENT_ID="project-x-client"
KEYCLOAK_CLIENT_SECRET="<secret-from-project-x-client>"
KEYCLOAK_REDIRECT_URI="https://project-x-domain.com/auth/keycloak/callback"
Notice that KEYCLOAK_REALM
is the same for both, but the CLIENT_ID
, CLIENT_SECRET
, and REDIRECT_URI
are specific to each application.
Step 5: Configure Services (config/services.php
)
This step is identical for all projects. Open config/services.php
in each project and add:
php'keycloak' => [
'client_id' => env('KEYCLOAK_CLIENT_ID'),
'client_secret' => env('KEYCLOAK_CLIENT_SECRET'),
'redirect' => env('KEYCLOAK_REDIRECT_URI'),
'base_url' => env('KEYCLOAK_BASE_URL'),
'realm' => env('KEYCLOAK_REALM'),
],
Step 6: Create Routes (routes/web.php
)
This step is identical for all projects. Open routes/web.php
in each and add:
phpuse App\Http\Controllers\Auth\KeycloakController;
Route::get('/auth/keycloak/redirect', [KeycloakController::class, 'redirect'])->name('keycloak.login');
Route::get('/auth/keycloak/callback', [KeycloakController::class, 'callback']);
Step 7: Create the Controller
This step is also identical for all projects.
- In each project’s terminal, run:
php artisan make:controller Auth/KeycloakController
- Open the newly created
app/Http/Controllers/Auth/KeycloakController.php
and paste this code:
php<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User; // Make sure this namespace is correct for the project
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Laravel\Socialite\Facades\Socialite;
class KeycloakController extends Controller
{
public function redirect()
{
return Socialite::driver('keycloak')->redirect();
}
public function callback()
{
$keycloakUser = Socialite::driver('keycloak')->user();
// JIT (Just-In-Time) Provisioning:
// Find a user with the Keycloak ID or create a new one.
$user = User::updateOrCreate(
[
'email' => $keycloakUser->getEmail(), // The unique, unchanging identifier
],
[
'name' => $keycloakUser->getName(),
'password' => Hash::make(Str::random(24)), // Random password, not used for login
]
);
// Log the user into the current application
Auth::login($user);
// Redirect to the application's home page
return redirect('/home'); // Or redirect()->route('project.home');
}
}
User Provisioning Note: The code above automatically creates a user record in each application’s database the first time they log in. This is called Just-In-Time Provisioning and is a standard SSO practice.
Step 8: Add the Login Button
In each application’s login page (resources/views/auth/login.blade.php
), add the button:
xml<a href="{{ route('keycloak.login') }}" class="btn btn-secondary">
Login with SSO
</a>
Step 9: (Crucial) Protect Routes
For SSO to be effective, you must ensure that pages requiring a login are protected by Laravel’s auth
middleware. When an unauthenticated user tries to access a protected page, Laravel will automatically redirect them to the login page, where they will see the “Login with SSO” button.
Example in routes/web.php
:
phpRoute::middleware(['auth'])->group(function () {
// All routes inside this group require a user to be logged in.
// e.g., Route::get('/dashboard', [DashboardController::class, 'index']);
});
The Result
Once you have completed these steps for all your Laravel projects, the SSO flow will work exactly as described. A user can log in to Eventmie Pro, and when they navigate to Project X, they will be logged in automatically, creating a seamless, unified user experience across your entire application ecosystem.