italia/spid-laravel
A Laravel package for integrating SPID, Italy’s digital identity system, into your application. It provides ready-to-use authentication routes, middleware, and configuration so users can sign in securely with their SPID credentials.
Install the package and its underlying SAML library:
composer require italia/spid-laravel
Laravel will auto-discover Italia\Spid\Laravel\SpidServiceProvider. On older versions you must register the provider and the Spid facade alias manually in config/app.php.
Publish the config and views:
php artisan vendor:publish --provider="Italia\Spid\Laravel\SpidServiceProvider"
Where to look first:
config/spid.php — this is the whole integration. It holds the SP entity ID, ACS/SLO URLs, X.509 certificate and private-key paths, the IdP list, the user_model used for auto-provisioning, and the spid_test switch.php artisan route:list | grep spid — confirms the routes the package registered (/spid/login, /spid/login/{idp}, /spid/response, /spid/logout, /spid/metadata).vendor/italia/spid-laravel/src — the controller and the user-mapping logic are small; read them before customizing.First use case: a working local login against the SPID test IdPs. Set spid_test => true, point sp_assertion_consumer_service_url at https://your-app.test/spid/response, install the test certificate/key from the SPID test registry, add a "Login with SPID" link to your login page, and walk the flow end to end. When that round trip creates a user and logs them in, you understand the package. Registering the ACS URL in the SPID registry is the step that turns this into production.
Treat SPID as a login method, not a gate. Keep standard auth middleware on your routes and let SPID be one way to populate the session. The ACS handler logs the user in with Laravel's session guard and redirects to your configured home route; everything downstream is ordinary Laravel auth.
Deep-link the IdP. /spid/login renders the IdP chooser view. /spid/login/{idp} skips it and goes straight to a specific IdP (poste, aruba, spid-test1, …). Use this for "remember my IdP" cookies or IdP-specific landing pages.
Own the attribute mapping. SPID returns spidCode, fiscalNumber (TINIT-RSSMRA80A01H501U), name, familyName, email, mobilePhone, and address/date attributes. Use spidCode or the normalized fiscalNumber as the stable join key. The package's default auto-provisioning is fine for prototypes, but most real apps subclass the controller or hook the post-auth event to normalize the CF prefix, backfill names, and attach SPID to an existing email-matched account instead of creating a duplicate.
Publish and brand the views. The IdP chooser is a plain Blade view. You'll want your logo, a privacy notice, and an "other login methods" link. Publish it and edit — don't fight the package default.
Expose metadata properly. /spid/metadata (or Spid::getMetadata()) emits the SP metadata XML you upload during AgID registration. Serve it over the same stable HTTPS URL you'll hard-code into the config, or you'll re-register later.
Handle logout deliberately. Call Auth::logout() for the local session. Use the SPID SLO route only if your agreement requires propagating logout to the IdP — IdPs implement SLO inconsistently, so treat it as best-effort and never block on it.
Test in layers. Unit-test your attribute mapping and user creation in isolation. For feature tests, assert that the ACS rejects tampered or unsigned responses rather than trying to fabricate a full SAML round trip; a live test-IdP smoke test covers the integration.
onelogin/php-saml validator. This is the single most common deployment failure.VerifyCsrfToken, and SESSION_SAME_SITE=strict will drop the session cookie on the POST and silently log the user out. Use lax.NotBefore/NotOnOrAfter windows are tight; a drifted app server produces "assertion not yet valid" or "expired" with no useful stack. Run NTP everywhere.config:cache freezes nested env() calls. Keep every env() read at the top level of config/spid.php, or caching will silently pin stale values in production.spid_test. Leaving it on in production shows test IdPs or validates against test certificates. Derive it from APP_ENV and assert at boot if you can.email and mobilePhone are frequently absent. Make those columns nullable and fall back to the fiscal code.fiscalNumber. Strip the TINIT- prefix before storing or comparing, or you'll get duplicate accounts.spid-php; check provider/middleware compatibility with your Laravel major before upgrading, and keep the config and views vendored rather than relying on defaults.debug flag in staging and log lastErrorReason from the response validator — raw exceptions alone rarely tell you whether it was a signature, audience, or timing failure.Spid facade directly when you outgrow auto-provisioning. The facade exposes the underlying SP session, so step-up auth and attribute refreshes are yours to build.How can I help you explore Laravel packages today?