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

Sso Library Laravel Package

korotovsky/sso-library

korotovsky/sso-library is a Laravel package for implementing single sign-on across multiple applications. It lets users authenticate once and access connected Laravel apps, simplifying shared login flows and centralizing authentication.

View on GitHub
Deep Wiki
Context7

Getting Started

Read the framing before the code: the two descriptions disagree. The package blurb calls it "Laravel/PHP," but the repository is a Symfony2 bundle (a Bundle class, a DependencyInjection extension, and a security.firewalls.*.sso factory). There is no composer require path into a modern Laravel app — Symfony2-era constraints target PHP 5.x/7.0 and will fail platform checks on 8.2+. Treat install as a non-goal on day one.

Where to look first, in this order:

  1. Clone the repo and read DependencyInjection/ and the security firewall factory — this is where the broker URL, client credentials, and callback route are wired. That file is effectively the configuration reference; there is no Laravel-style config/sso.php because Laravel isn't the target.
  2. Read the request listener / authentication provider pair. That is the actual protocol: what it reads off the request, what it calls on the broker, what it does with the response, and where it establishes the session.
  3. Read the controller(s) that handle the broker-side login and the client-side callback. This is the ticket/token handoff, and it is the only part worth porting.

The first use case: a scratch Laravel 11 app on PHP 8.2 where you hand-roll the flow the package describes — a GET /auth/sso/redirect that bounces the browser to the broker's login with a callback URL, a GET /auth/sso/callback that takes the returned ticket, validates it server-side against the broker, resolves a local User, and calls Auth::login($user, true). Build that against a fake broker (a route in the same app that mints tickets) before touching the real library. If your callback works against a fake broker and the package's code confirms the same wire format, you have what you need. Everything after that is your code, not theirs.

Write the wire-format note before you write the adapter. Endpoints, HTTP verbs, query/body parameter names, ticket format and lifetime, whether validation is back-channel or signature-based, cookie names, and the error codes. That note is the deliverable; the ported PHP is disposable.

Implementation Patterns

Extract the protocol core, delete the Symfony plumbing. Copy the ticket-validation and response-parsing classes into app/Support/Sso (or a private package). Strip Symfony\Component\HttpFoundation\Request, Session, and Container references and replace their arguments with plain scalars, a PSR-7 request, or a small SsoResponse value object. Never shim Symfony's request object into Laravel — it drags the whole HTTP kernel in behind it.

Prefer middleware + Auth::login() over a custom guard. A sso.auth guard via Auth::extend() sounds idiomatic but fights you: SSO here is a redirect round-trip, not a stateless credential check, so a guard ends up holding request state it can't see. The cleaner shape is two routes plus one middleware:

Route::get('/auth/sso/redirect', [SsoController::class, 'redirect'])->name('sso.redirect');
Route::get('/auth/sso/callback', [SsoController::class, 'callback'])->name('sso.callback');

with the callback doing validate → resolve → Auth::login($user, true) → redirect()->intended(...). Keep the middleware for protecting routes (auth plus an EnsureSsoSession that checks the broker session is still live if you support single logout).

Model identity attachment explicitly, not by email alone. Add an sso_identities table (provider, subject, user_id, unique on provider+subject) rather than looking users up by email every time. Email is mutable at the IdP and is a weak join key; the subject/identifier is not. The package's "configurable user attachment" is a closure that receives the SSO payload and returns a User — mirror that as a config-bound resolver so tests and multi-tenant installs can swap it:

// config/sso.php
'resolve_user' => fn (SsoIdentity $id) => User::firstOrCreate(
    ['email' => $id->email],
    ['name' => $id->name, 'password' => Str::random(64)]
),

Validate tickets server-side, always. The callback's ?ticket=... is an opaque pointer, never an identity. Exchange it back-channel, bind the validation to the exact callback URL you sent, and consume it once. Store used tickets in the cache with a TTL slightly longer than the broker's own:

abort_unless(Cache::add("sso:ticket:{$ticket}", true, now()->addMinutes(5)), 401);

Implement local logout and global logout as separate actions. logout forgets the Laravel session; sso.logout also invalidates at the broker and redirects. Getting this wrong produces the classic "logged out here, still logged in there" loop.

Test against a fake broker, not the real thing. A FakeBroker test double that mints valid, expired, replayed, and tampered tickets gives you the four tests that actually matter — happy path, replay rejected, expired rejected, wrong-audience rejected. Feature tests through $this->get('/auth/sso/callback?ticket=...') with RefreshDatabase will catch almost everything.

Gotchas and Tips

  • It will not install. Expect composer require to fail on PHP constraints, and --ignore-platform-reqs to get you a package that fatals on PHP 8.2 for era-typical reasons (each(), ${var} interpolation, dynamic properties, missing return types). Do not plan around making it install.
  • Fail closed. The single most common bug when porting security code is a broad catch (\Exception $e) { return true; } around validation, or a try that lets the user through on a network error to the broker. Any error in the validation path must be a 401.
  • Replay protection is usually missing or weak in libraries of this vintage. If the ticket isn't single-use and bound to the consuming client, add both. A Cache::add guard is two lines and closes the hole.
  • Check the validations the library doesn't do. Destination/audience matching, InResponseTo correlation, and signature-algorithm rejection (SHA-1 defaults were common in this era) are frequently absent. Add them in your adapter and write a test per check.
  • Clock skew. Allow a small leeway (30–120 seconds) on NotBefore / NotOnOrAfter; zero tolerance causes intermittent failures across hosts, and generous windows are a security smell. Make it configurable.
  • Signing-key rotation is the silent killer. If the broker rotates its cert, every login fails at once with an opaque error. Cache broker metadata with a short TTL and a forced-refresh on validation failure, plus an alert on auth failure-rate spikes.
  • Cookie and domain topology. Cross-subdomain SSO lives or dies on SESSION_DOMAIN, SESSION_SECURE_COOKIE, and SameSite. A SameSite=Strict session cookie will be dropped on the redirect back from the broker and produce a login loop that only reproduces on staging. Use Lax for the callback.
  • Open redirect via returnTo / RelayState. Whitelist allowed hosts and paths before redirect()->intended(); the intended-URL mechanism is otherwise an attacker-controlled redirect after a successful login.
  • Config caching bites. Never call env() outside config/sso.php — under php artisan config:cache it returns null and your broker URL vanishes in production only.
  • Logging. Log the ticket id, correlation id, client id, and outcome — never the full assertion, token, or raw broker response. If you can't debug a failed login from logs without seeing secrets, add a redacted payload hash.
  • Extension points are aspirational. The blurb mentions "extensible contracts"; in practice the seams are Symfony's firewall factory and event subscriber. Forking is the extension mechanism. Budget for an owner, a patch cadence, and a documented exit to a maintained library before this reaches production — and if no one will own it, reimplement against the note and move on.
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle