tesda/keycloak-auth

Keycloak SSO OpenID Connect integration for Laravel applications.

Maintainers

Package info

github.com/Nyanta2598/keycloak-auth

pkg:composer/tesda/keycloak-auth

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.0 2026-07-02 01:33 UTC

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 (OIDC sub).
  • 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_hint handling (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:

  1. 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;
    }
}
  1. 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:

  1. 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);
    }
}
  1. 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) [Accepts GET and POST]

License

This package is open-source software licensed under the MIT license.