A Developer’s Guide to Integrating Keycloak SSO with Laravel 12
In this guide, we’ll walk through a popular and flexible method for integrating Keycloak with a Laravel 12 application. Instead of forcing all users through Keycloak, we will add a “Login with Keycloak” button to the existing login page. This gives users the choice between traditional password-based login and a seamless Single Sign-On (SSO) experience.
This approach uses Laravel Socialite, the standard for handling OAuth-based authentication from third-party providers.
Step 1: Verify Your Keycloak Client Configuration
This is a critical step. A mismatch in the redirect URI is the most common cause of errors in a Socialite flow.
- Log in to your Keycloak Admin Console (usually
http://localhost:8080
). - Navigate to your realm (e.g.,
laravel-app
). - Go to Clients and select the client you created (e.g.,
laravel-client
). - In the client settings, ensure the Valid Redirect URIs field contains the exact callback URL you set in your
.env
file. It should be:http://127.0.0.1:8000/auth/keycloak/callback
If this URL is missing or incorrect, add it and save the changes.
Step 2: Test the Login Flow as a User
Now, let’s simulate the user’s journey. It’s highly recommended to use a private or incognito browser window to avoid any conflicts with existing login sessions.
- Navigate to the Login Page: Open your private browser window and go to your Laravel application’s login page:
http://127.0.0.1:8000/login
- Click the Keycloak Button: You should see the standard Laravel login form and your new “Login with Keycloak” button. Click it.
- Redirection to Keycloak: Your browser should immediately redirect you to the Keycloak login page. The URL in the address bar will change to
http://localhost:8080/...
. - Log In with Keycloak Credentials: Enter the username and password for the test user you created in Keycloak (e.g.,
testuser
). Click “Sign In”. - Redirection Back to Laravel: After a successful login, Keycloak will redirect you back to your Laravel application. Based on the logic in your
KeycloakController
, you should land on the/home
page, fully authenticated.
Step 3: Verify the User in Your Database
The final step is to confirm that the callback
method in your controller worked correctly and created a new user in your local database.
- Open your preferred database management tool (like phpMyAdmin, TablePlus, or Sequel Ace).
- Connect to your Laravel application’s database (e.g.,
laravel_rbac
). - Open the
users
table.
You should see a new entry for the user you just authenticated with Keycloak. The user’s email
and name
should be populated with the information from their Keycloak account.
If you have successfully completed all these steps, your Keycloak integration is fully functional. You have successfully implemented a dual-authentication system, giving your users the flexibility to log in with either local credentials or their centralized Keycloak account.
Step 4: Revert to Laravel’s Default Authentication
If you have previously attempted other SSO integrations (like a guard-based redirect), it’s crucial to revert your config/auth.php
file back to Laravel’s default settings to avoid conflicts. This ensures that Laravel’s standard session authentication is active, which we will then extend with our SSO provider.
Open config/auth.php
and ensure your guards
and providers
arrays look like this:
php// config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
],
After saving the file, clear your configuration cache to apply the changes:
bashphp artisan config:clear
Step 4: Install and Configure the Keycloak Socialite Package
First, we need to add the necessary package to our project using Composer:
bashcomposer require socialiteproviders/keycloak
Next, configure your application’s environment variables by opening the .env
file and adding your Keycloak server details:
text# .env file
KEYCLOAK_BASE_URL=http://localhost:8080
KEYCLOAK_REALM=laravel-app
KEYCLOAK_CLIENT_ID=laravel-client
KEYCLOAK_CLIENT_SECRET=your-client-secret-from-keycloak
KEYCLOAK_REDIRECT_URI="http://127.0.0.1:8000/auth/keycloak/callback"
Now, tell Laravel about the Keycloak service by adding an entry to the config/services.php
file:
php// config/services.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 5: Register the Socialite Event Listener
In modern Laravel, the app/Providers/EventServiceProvider.php
file may not exist by default. We need to create it to register our Socialite provider.
First, run the Artisan command to generate the file:
bashphp artisan make:provider EventServiceProvider
Now, open the newly created app/Providers/EventServiceProvider.php
and add the event listener for the Keycloak Socialite provider to the $listen
array:
php// app/Providers/EventServiceProvider.php
protected $listen = [
\Illuminate\Auth\Events\Registered::class => [
\Illuminate\Auth\Listeners\SendEmailVerificationNotification::class,
],
// Add this entry for the Keycloak provider
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
\SocialiteProviders\Keycloak\KeycloakExtendSocialite::class.'@handle',
],
];
Laravel will automatically discover and load this service provider.
Step 6: Create the Authentication Routes and Controller
This SSO flow requires two routes: one to redirect the user to Keycloak and a callback route for Keycloak to return the user to.
First, create the controller that will handle the logic:
bashphp artisan make:controller Auth/KeycloakController
Next, add the routes to your routes/web.php
file:
php// routes/web.php
use App\Http\Controllers\Auth\KeycloakController;
Route::get('/auth/keycloak/redirect', [KeycloakController::class, 'redirect'])->name('keycloak.login');
Route::get('/auth/keycloak/callback', [KeycloakController::class, 'callback']);
Now, open app/Http/Controllers/Auth/KeycloakController.php
and add the business logic. This code will handle the redirect and, upon the user’s return, create or find their account in your local database before logging them in.
php<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
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();
$user = User::updateOrCreate(
[
'email' => $keycloakUser->getEmail(),
],
[
'name' => $keycloakUser->getName(),
'password' => Hash::make(Str::random(24)), // Create a random, unusable password
]
);
Auth::login($user);
return redirect('/home');
}
}
Step 7: Add the SSO Button to Your Login Page
Modify your resources/views/auth/login.blade.php
file to include a “Login with Keycloak” button. This gives users a clear choice.
xml<!-- resources/views/auth/login.blade.php -->
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Login') }}</div>
<div class="card-body">
<!-- Existing Login Form -->
<form method="POST" action="{{ route('login') }}">
@csrf
{{-- ... form fields ... --}}
<div class="row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Login') }}
</button>
</div>
</div>
</form>
<hr>
<!-- Keycloak Login Button -->
<div class="text-center">
<a href="{{ route('keycloak.login') }}" class="btn btn-secondary">
Login with Keycloak
</a>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
Step 8: The Final Test – End-to-End Verification
With everything configured, it’s time to test the full flow.
- Start Your Servers: Ensure both your Keycloak instance (via
docker-compose up
) and your Laravel development server (php artisan serve
) are running. - Verify Keycloak Configuration: Log in to your Keycloak admin console, navigate to your client, and confirm that
http://127.0.0.1:8000/auth/keycloak/callback
is listed under Valid Redirect URIs. This is a critical step. - Test the User Flow:
- Open a private or incognito browser window and go to
http://127.0.0.1:8000/login
. - Click the “Login with Keycloak” button.
- You should be redirected to the Keycloak login page. Enter your test user’s credentials.
- After logging in, you should be redirected back to your Laravel application’s
/home
page, fully authenticated.
- Open a private or incognito browser window and go to
- Verify Database Entry: Check the
users
table in your application’s database. You should see a new record for the user who just logged in, with their name and email populated from Keycloak.
Congratulations! You have successfully implemented a dual-authentication system, offering your users the security and convenience of SSO.