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 Saml2 Laravel Package

jeffersongoncalves/laravel-saml2

Laravel SAML2 package for adding SAML 2.0 single sign-on to your app. Configure an identity provider, handle SP-initiated login and logout, and map SAML assertions to Laravel users for enterprise SSO integration.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a multi-tenant SAML2 service-provider package: it holds per-tenant IdP configuration in a saml2_tenants table and wires that into the SAML login/logout/metadata flows.

Install (v1.1.0 flow):

composer require <vendor>/laravel-saml2
php artisan vendor:publish --tag=saml2-config
php artisan vendor:publish --tag=saml2-migrations
php artisan migrate

Note the migration is now a published stub, not something the package runs. If you skip the vendor:publish step you get a config file and no saml2_tenants table, and the failure surfaces later as a query error on the first login attempt rather than at boot.

Where to look first:

  1. config/saml2.php — routes, guards, tenant resolution, debug flags.
  2. The published migration — it tells you exactly which columns the package expects (entityId, ssoUrl, x509cert, slsUrl, etc.) and is the source of truth for your tenant model/factory.
  3. The package's route registrations — you need to know the ACS and metadata URLs before you can register the SP with an IdP.

First use case: get one tenant logging in end-to-end against a test IdP (samltest.id is the fastest loop) by seeding a single saml2_tenants row, hitting the login route, and confirming the ACS callback establishes an authenticated session. Only after that works should you add tenant resolution — debugging multi-tenancy and SAML signature validation at the same time is miserable.

Implementation Patterns

Tenant resolution belongs in your app, not the package. Resolve the tenant in middleware (subdomain, path prefix, or a header) and bind it into the container so the SAML flow reads it consistently. Keep the resolution logic in one class — it's the piece you'll unit test most.

Seed tenants, don't hand-edit rows. A Saml2TenantFactory plus a seeder makes RefreshDatabase tests trivially reproducible. Because the migration is now an app-owned stub, tests running migrations in-memory work without any package-side migration registration hacks.

Route layout: if you're multi-tenant, prefix the package routes per tenant (e.g. /{tenant}/saml/acs) so the ACS URL embedded in the AuthnRequest matches the tenant. Register the SP metadata URL per tenant with each IdP — most IdPs cache metadata aggressively, so a URL change means re-registration.

Attribute mapping: treat the assertion as untrusted input. Map NameID/attributes to a local user in a single dedicated action, then Auth::login($user). Keep the mapping table in config or a per-tenant column so onboarding a new IdP doesn't require a deploy.

Deploy script:

php artisan vendor:publish --tag=saml2-migrations --force
php artisan migrate --force

--force matters because vendor:publish silently no-ops on an existing file — without it, an upgrade that changes the stub leaves your old copy in place and you'll never see the change.

Testing: don't try to forge signed assertions. Unit-test tenant resolution and attribute mapping against fixture payloads, and do one real end-to-end against a sandbox IdP per release. That's the only layer where signature/canonicalization bugs actually show up.

Gotchas and Tips

  • Upgrade from 1.0 is genuinely a no-op, but clean up your config. The run_migrations key no longer exists. Leaving it in config/saml2.php is harmless today but will confuse the next reader, and if the package later validates config keys strictly it becomes a boot failure. Delete it.
  • The "safe to publish and migrate anyway" claim depends on the stub you publish. The idempotency (keep existing table, add only missing columns) lives in the published migration file, not in the package. If you've previously hand-written or edited a saml2_tenants migration, publishing plus migrate will not reconcile the two — diff them.
  • You now own migration drift. Future package releases that alter the schema will not reach you automatically; you must re-publish (with --force) and review the diff. Add a note to your upgrade checklist.
  • config:cache versus per-tenant config. If you swap SAML config at runtime per tenant, a cached config repository can bite you. Set values on the repository for the request and never assume they persist; anything stored statically leaks across tenants in long-running workers (Octane, queue workers).
  • CSRF and session state. The ACS route must be exempt from CSRF, and multi-node deployments need a shared session/cache store for the SAML request ID and relay state — otherwise logins fail intermittently behind a load balancer and look like signature errors.
  • URL generation behind proxies. Trusted-proxy config must be correct or the ACS URL in the AuthnRequest won't match the registered one, producing Invalid audience/Recipient mismatch rather than anything obviously proxy-related.
  • Certificate formatting. x509cert values in tenant rows commonly need the PEM header/footer stripped or, inversely, restored with real newlines — a cert stored with literal \n in the DB is the single most common "invalid signature" cause.
  • Debugging order: turn on the package's debug output, log the raw SAML response XML before validation, then distinguish InvalidSignature (cert/formatting/canonicalization) from Response validation failed (audience, expiry, clock skew, replay). Check server clock skew before touching crypto.
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.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox