codegreencreative/laravel-samlidp
A Laravel package that turns your app into a SAML Identity Provider (IdP), with SSO endpoints, service provider management, metadata, and certificate handling so Laravel can authenticate users for external SAML service providers.
v5.4.0 is a compatibility-only release: it adds Laravel 13.x support with no new features, config keys, or API changes. Treat it as a green light to run the package on Laravel 13, not as an upgrade that requires code changes.
composer require codegreencreative/laravel-samlidp. On Laravel 13 you need ^5.4; on Laravel 12 or older, ^5.3 remains fine. If Composer refuses to resolve, run composer why-not codegreencreative/laravel-samlidp 5.4.0 and check the PHP floor (Laravel 13 raises it) plus the robrichards/xmlseclibs / SAML toolkit transitive constraints. The service provider is auto-discovered.php artisan vendor:publish --provider="CodeGreenCreative\SamlIdp\SamlIdpServiceProvider" gives you config/samlidp.php — this is the first file to read, since it holds the base URL, cert/key paths, SP definitions, and signing/encryption settings.php artisan list for the exact samlidp:* signature in your version) or generate manually with openssl req -x509 -newkey rsa:2048 -nodes. Store both files outside the web root (e.g. storage/app/samlidp/), chmod 600 the key, and point cert_path / key_path at absolute paths.SAML_IDP_BASE_URL must be the exact HTTPS origin the SPs will call. Everything in the metadata (entity ID, SSO/SLO endpoints, ACS URLs) is derived from it.CodeGreenCreative\SamlIdp\Events\SamlLogin and SamlLogout in EventServiceProvider (or Event::listen in a service provider).https://your-app.test/saml/metadata. First use case: point a free SP sandbox or a local test SP at that URL, hit /saml/login from the SP, and confirm you land back at the SP's ACS with a valid Assertion and the attributes you expect.SP-initiated SSO (the default flow). The SP redirects the browser to your SSO endpoint with an AuthnRequest. The package parses and validates it, then hands control to you. Your SamlLogin listener should resolve/authenticate the user (session, remember-me, SSO against an upstream IdP) and make sure Auth::user() is populated before the response is built — the assertion attributes are read from the authenticated user afterwards. Keep the listener thin: delegate to an action class so it is unit-testable without HTTP.
Attribute mapping as a first-class concern. Don't scatter getAttribute() calls through listeners. Put the claim set (email, uid, displayName, roles, groups) in one place — a config array or a small SamlAttributes class — keyed off the user model. This is the single highest-leverage abstraction in the package: every SP wants different NameID and attribute names, and every new SP becomes a config diff instead of a code change.
Multiple SPs / multi-tenancy. The config supports a map of service providers keyed by entity ID. Resolve the SP from the Issuer on the incoming request rather than from a session or URL segment, otherwise a user with two SP tabs open gets the wrong assertion. For per-tenant branding or ACS URLs, layer a tenant-resolving middleware in front of the package routes.
IdP-initiated SSO. For "click the tile in our dashboard" launches, build a link to your login endpoint with the target SP plus a RelayState carrying the deep link. Note this path has no AuthnRequest to validate, so you own replay protection and the "which SP?" decision.
Single logout. Handle SamlLogout by invalidating the local session and flushing any app-level SSO state, then let the package return the LogoutResponse. Test both SP-initiated and IdP-initiated logout; they fail in different ways (stale session vs. broken redirect chain).
Testing. Write feature tests against the endpoints: build a signed AuthnRequest fixture (or grab one from a real SP's debug output), post it to the SSO endpoint, base64-decode the returned SAMLResponse, and assert on the assertion XML with DOMDocument + XPath. Assert the signature verifies rather than string-matching XML. For the attribute builder, plain unit tests are enough.
Deployment. php artisan config:cache and route:cache must be run after any env change; SAML failures after a deploy are frequently just a cached config with an old base URL. For certificate rotation, plan a dual-publish window — most SPs will not accept a silent key swap, so coordinate a metadata re-import before retiring the old cert.
base_url and the generated endpoints can drift to http:// or an internal host, producing metadata that SPs reject on signature/recipient mismatch. Fix with TrustProxies plus an explicit SAML_IDP_BASE_URL; never rely on APP_URL alone.php artisan serve, Octane, and queue workers.NotBefore/NotOnOrAfter errors that look like signing errors. Keep hosts on NTP.EventServiceProvider::$listen and run php artisan event:clear after editing.NameID stability. Changing the user identifier (email → UUID) breaks every SP that stores the NameID as a persistent key. Decide the format early and treat it as a public contract.config/samlidp.php in non-production, tail storage/logs/laravel.log, and validate responses with the SAML-tracer browser extension or xmlsec1 --verify before blaming the package. Most "bad signature" reports are malformed base64 (a + turned into a space by sloppy form encoding).^5.3 branch deployable until that passes.How can I help you explore Laravel packages today?