Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Keycloak Sso Laravel Package

edoaurahman/keycloak-sso

Integrate Keycloak single sign-on into Laravel apps. This package wires up Keycloak OAuth/OpenID Connect authentication, letting users log in through your Keycloak realm with configurable routes and middleware for a quick SSO setup.

View on GitHub
Deep Wiki
Context7

Getting Started

v4.0.0 is a security + support-boundary release. There are no new features and no application code changes, so the "getting started" story is unchanged from v3 — what changed is who can install it and what it pins you to.

Minimal path to first login:

composer require tekinfopg/sso-helper-laravel:^4.0
php artisan vendor:publish --tag=sso-helper-config   # check the tag in the package README
php artisan migrate                                  # only if you use its user/identity tables
  1. Read the published config file first. It is the single source of truth for this package: endpoint/metadata URLs, client id/secret env keys, guard name, routes to register, and the user-mapping callback. Everything you'll debug later lives here.
  2. Set the env vars the config reads (typically issuer/discovery URL, client id, client secret, redirect URI). Keep them in .env.example so the next developer doesn't reverse-engineer the config.
  3. Check the routes it registers with php artisan route:list --path=sso (or whatever prefix the config uses). You usually do not hand-write the callback controller.
  4. First use case to validate end-to-end: protect one route group with the package's middleware, hit it logged out, complete the IdP round-trip, and confirm Auth::user() is populated. Do this before wiring anything else — it exercises config, routes, session, and user provisioning in one pass.

If you're on Laravel 8/9 or PHP < 8.2, you cannot take this release. Pin ^3.0 deliberately and record it as technical debt; see Gotchas.

Implementation Patterns

Guard-level integration. Treat the package as an authentication guard/driver rather than a set of helpers you call ad hoc. Configure it in config/auth.php under a dedicated guard and use auth:your-guard in middleware. This keeps the SSO session separate from any local web guard and lets you keep password login for break-glass admin accounts.

Route group pattern. Put the login/callback/logout routes outside your auth middleware group (they're the entry point), then wrap the rest:

Route::middleware(['web', 'auth:sso'])->group(function () {
    Route::get('/dashboard', DashboardController::class);
});

User provisioning is your integration point, not the package's. Most SSO helper packages expose a "map/retrieve user from IdP claims" hook in config or via a bound contract. Implement it explicitly:

  • Decide your identity key (subject/sub vs email) and never key on email alone if the IdP allows email changes.
  • Store the IdP subject id in its own column so you can re-link accounts later.
  • Decide create-on-first-login vs reject-unknown-user. Rejecting is safer for internal tools; creating is fine for consumer apps.
  • Sync mutable attributes (name, groups/roles) on each login, but treat IdP roles as one input to your authorization, not the whole story — otherwise an IdP misconfiguration becomes a Laravel privilege escalation.

Logout needs two halves. Local session invalidation plus, if the package supports it, IdP single-logout (or at least redirect to the IdP's end-session endpoint). Test the "log out, hit back button, hit protected route" sequence — a local-only logout that leaves an IdP cookie is a classic finding in security review.

Local development without an IdP. Add an environment-gated bypass, e.g. a route/service-provider branch that logs in a seeded test user when SSO_FAKE=true and app()->environment('local'). Guard it hard: abort_unless(app()->environment('local')) inside the branch, not just an env check in a config file that could be cached wrong. Never ship a bypass that keys off an env var alone.

Testing. Use Laravel's actingAs($user, 'sso') for everything downstream of authentication — that's the 95% case and it keeps tests fast and IdP-free. Reserve one thin integration test for the callback route using a stubbed HTTP response (Http::fake()) with a representative claims payload. Assert the claims-to-user mapping there, since that's the part your application actually owns.

Multi-tenant / multi-IdP. If your app serves several tenants, you'll likely need per-tenant config resolution (tenant → issuer/client id). Do this by resolving config at request time in a service provider or a custom resolver bound into the container, not by mutating config() mid-request after the guard has already booted.

CI gate. Add composer audit --locked to CI. v4.0.0 ships conflict rules against specific vulnerable versions, so a green audit locally but a red install in CI almost always means a stale lockfile or a transitive pin.

Gotchas and Tips

v4.0.0's breaking changes are install-time, not runtime. Dropping PHP < 8.2 and Laravel 8/9 means the failure mode is composer update refusing to resolve — not an exception at runtime. Read the resolver error carefully before assuming it's the SSO package's fault.

The conflict rules will surface in unrelated-looking packages. v4.0.0 blocks vulnerable releases of symfony/http-foundation, symfony/http-kernel, symfony/mime, nesbot/carbon, guzzlehttp/psr7, phpseclib/phpseclib, firebase/php-jwt, and others. If you're on an older Laravel 10.x that pins a pre-patch symfony/http-foundation, you'll get a conflict that names Symfony even though you only asked for the SSO package. Fix is to bump Laravel's patch version — not to loosen the SSO constraint. Do not work around this with --ignore-platform-reqs or a replace hack; you'd be reinstalling the CVEs the release exists to close.

Guzzle floor is ^7.15.2. If a sibling package in your monorepo requires guzzlehttp/guzzle:^6 or a lower 7.x, that package is now the blocker. This is the most likely upgrade friction point for older apps.

Upgrading is a two-line change with zero code edits — so keep the diff honest. The release explicitly says no code changes are required. If your upgrade PR touches application code, stop and ask why. Upgrade in one commit, deploy, verify the login round-trip, then merge.

Legacy apps: pin v3 on purpose. For a Laravel 8/9 service, composer require tekinfopg/sso-helper-laravel:^3.0 is correct, but write the constraint as ^3.0 (not *, not dev-main) and add a ticket. A wildcard constraint will silently pull v4 later and break the build on the PHP floor.

Verify the PHP floor in CI, not just locally. If your CI image is php:8.1, the composer install fails before tests run. Check composer.json's platform config and any config.platform.php override — an override set to 8.1 will produce misleading resolution errors against v4.

config:cache hides config mistakes. After publishing config, always test with php artisan config:clear locally and with config:cache in a staging deploy. A closure in the config file (common in user-mapping hooks) is not serializable and will blow up only under config:cache — a classic "works on my machine" for this class of package. Move mappings into a class and reference it by FQCN string.

Redirect loops are almost always session/domain config. If the callback lands you back at the IdP or bounces to login, check in this order: APP_URL vs the registered redirect URI (exact string match, including trailing slash and scheme), SESSION_DOMAIN, and whether the callback route is inside a middleware group that redirects unauthenticated users.

Debug the round-trip with the callback payload, not the package internals. Log the claims array at the callback (guarded, redacted, non-production) before it hits your user mapper. Nine out of ten "SSO doesn't work" issues are a claims shape mismatch or a missing sub, not a bug in the package.

Clock skew and token lifetime. firebase/php-jwt and similar validators reject tokens outside their nbf/exp window. Container clocks drifting a few minutes will produce intermittent auth failures that vanish on retry. If you see sporadic callback failures, check NTP before touching code.

Extension points, in order of preference: published config → bound contract/interface in the container → package event listeners → forking. Avoid subclassing package internals; a security release like v4 is exactly the moment internal APIs are least safe to depend on.

Keep an eye on v3 for security backports. Dropping Laravel 8/9 is reasonable, but if you're stuck on v3, confirm with the maintainer whether the same CVE floors get backported to a v3.x patch. If not, your Laravel 8/9 app is carrying known CVEs in transitive dependencies and that needs to be an explicit, tracked risk decision — not an accepted default.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core