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

Laravel Saml Laravel Package

overtrue/laravel-saml

A Laravel package for SAML 2.0 single sign-on. It provides configurable identity provider settings, login/logout routes, and a straightforward integration for adding SSO authentication to Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Check your platform first. 2.x requires PHP 8.3+ and Laravel 13.x. If you're on Laravel 9–12, stay on the 1.x line — pin "overtrue/laravel-saml": "^1.0" and don't let a composer update drag you across the major. The 2.0.0 release is a compatibility/maintenance major, not a feature major: SAML APIs, config keys, security defaults, validation policy, and logout response behaviour are all unchanged.

Install and publish:

composer require overtrue/laravel-saml:^2.0
php artisan vendor:publish --tag=saml-config   # check the exact tag in the README

First place to look: the published config/saml.php. It holds the SP block (entity ID, ACS/SLS URLs, signing key + cert) and the IdP block (SSO/SLO endpoints, x509 cert, binding preferences). Everything you'll debug later traces back to these values.

First use case — SP-initiated login against a real IdP (Okta, Entra ID, Auth0, Keycloak, ADFS):

  1. Fill in the SP and IdP blocks; set the IdP's ACS/redirect URLs to match your app's ACS and login routes exactly.
  2. Pull the SP metadata endpoint (/saml/metadata by default) and upload it to the IdP, or copy the entity ID + ACS URL in manually.
  3. Hit the login route, authenticate at the IdP, and confirm you land back on ACS with a valid session.
  4. In the ACS handler, map the assertion's NameID / attributes onto your User model and Auth::login() them.

Get that single flow working end-to-end before touching logout, SLO, or multi-IdP — it exercises config, certificates, clock skew, sessions, and routing in one shot.

Implementation Patterns

Prefer the package's route set; override only the handler. The default metadata / login / ACS / SLS routes plus the package middleware are what the release notes explicitly tell you to preserve. The clean extension point is your own controller or listener for the "consume assertion → provision user" step, not re-implementing the protocol plumbing:

// ACS: assertion is already validated by the package at this point
$nameId = $samlUser->getNameId();
$email  = $samlUser->getAttribute('email')[0] ?? $nameId;

$user = User::firstOrCreate(['email' => $email]);
Auth::login($user, remember: true);
return redirect()->intended('/dashboard');

Keep JIT provisioning idempotent and keyed on a stable attribute — NameID format varies wildly between IdPs (email vs. persistent opaque ID), so decide early and document it.

Multi-tenant / per-request IdP resolution. The 2.0.0 fix ("explicit IdP settings incorrectly invoking the configuration resolver") is the one that matters day-to-day: if you resolve an IdP per tenant/domain and pass the settings explicitly, those explicit values now win instead of being re-run through the resolver. Pattern:

$idp = Tenant::findByDomain($request->getHost())->samlConfig(); // array
Saml::withIdp($idp)->redirect();   // explicit settings are honoured as-is

If you previously worked around this by mutating config() at runtime, revisit that workaround — it may now be redundant, and config() mutation is fragile under config:cache anyway.

Signed responses vs. signed assertions. Most IdPs let you choose. Decide which one you validate and make it a config invariant, not a per-environment accident. 2.0.0 adds regression coverage for signed-response acceptance and unsigned/tampered-response rejection — mirror that in your own suite rather than trusting a green manual test.

Logout: handle both directions. SP-initiated logout goes through the IdP's SLO endpoint; IdP-initiated SLS arrives as an unsolicited POST to your SLS route. 2.0.0 explicitly preserves the logout response behaviour, so existing 1.x SLO integrations should carry over — verify anyway, since SLO is the most commonly broken part of any SAML setup.

Testing pattern. Use the package's new provider/metadata/login/logout/authentication tests as a template. For each environment-critical assertion, add three fixtures: valid signed, unsigned, and tampered (flip a byte in the assertion). Also cover request-ID mismatch — the release notes confirm this is now a tested rejection path, and it's the check that catches replay and stale-session bugs.

Gotchas and Tips

The upgrade is a Laravel-version gate, not a code rewrite. The only breaking change is the platform requirement. The real risk is silent breakage if you upgrade Laravel and the SAML package in the same window — do the Laravel 13 bump first, verify the app boots, then move the SAML package.

Follow the upgrade guide checklist explicitly. It calls out the four things that actually cause incidents: IdP certificates, strict validation mode, signing requirements, and your application-specific ACS/SLS routes and middleware. Diff your config/saml.php against the new stub and re-apply your customisations rather than overwriting.

Preserve strict mode and signing config. It's tempting to relax strict or wantAssertionsSigned when a staging IdP misbehaves. Don't ship that. Fix the IdP metadata or the certificate instead.

Certificate handling is the #1 support ticket. IdP certs rotate (often annually, sometimes with no warning), and the failure surfaces as an opaque assertion-validation error. Store the cert in config/env with a clear expiry note, and know how to swap it under pressure. Strip or preserve PEM headers deliberately — some IdPs publish certs without -----BEGIN CERTIFICATE----- and php-saml-based stacks will reject the mismatch. Check your clock/NTP too; even small skew breaks NotBefore/NotOnOrAfter.

CSRF and cookies break the POST binding. The ACS endpoint receives a cross-site POST from the IdP. Ensure the ACS route is excluded from CSRF and that session cookies are not blocked by SameSite=Strict. Behind a load balancer or TLS terminator, configure trusted proxies so generated ACS URLs stay https — a mismatched scheme produces an InResponseTo/destination validation failure that looks like a protocol bug.

Error handling got better — write your catch blocks accordingly. 2.0.0 preserves the original PHP Error/TypeError instead of raising a secondary TypeError inside AssertException. Two implications: (a) your logs will now show the real root cause, so re-read old incident notes with that in mind; (b) don't blanket-catch TypeError as a proxy for SAML failures any more — catch the package's SAML/assertion exception types and let genuine programmer errors surface.

config:cache is a footgun. Never mutate SAML config at runtime via config() in a way that only works uncached; always re-run php artisan config:cache after changing IdP values in deployed environments, and prefer explicit-settings calls (which 2.0.0 now handles correctly) over global mutation.

Debugging toolkit: SAML-tracer browser extension for inspecting the actual SAMLResponse, the IdP's own event/audit log, and the package's debug output (local only — it logs assertions, which are credentials). Keep a known-good signed SAMLResponse fixture around for offline comparison.

No live IdP test was performed for this release. Validation was 26 tests / 100 assertions across PHP 8.3–8.5, but the maintainers explicitly did not test against a real identity provider. After upgrading, manually verify login, assertion validation, and logout against your IdP in a staging environment before this reaches production — that gap is exactly where the certificate and clock-skew issues live.

Extension points worth knowing: custom route definitions/middleware overrides in config, a custom ACS controller, and event/listener hooks around authentication if your config exposes them. Reach for these before forking the package — the protocol layer is the part you least want to own.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
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