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

Sp Bundle Laravel Package

lightsaml/sp-bundle

Symfony bundle that adds SAML 2.0 Service Provider support via LightSAML. Configure SSO login/logout, consume IdP metadata, and validate assertions with minimal setup—ideal for adding enterprise single sign-on to Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check. lightsaml/sp-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, and no config/lightsaml_sp.php. In a Laravel codebase you have two realistic options:

  1. Port the idea, not the bundle. composer require lightsaml/lightsaml (the core library the bundle wraps) and wire the entity descriptors, credential store and request-state store yourself in a service provider. The bundle is essentially ~10 service definitions plus two controllers — you'd be re-implementing that wiring.
  2. Use the bundle only if you actually run a Symfony app (legacy service, sidecar admin, internal portal). Then composer require lightsaml/sp-bundle and register LightSaml\SpBundle\LightSamlSpBundle in config/bundles.php.

Be aware of the maintenance signal before committing: last release 2019-11-13, 64 stars, 0 dependents on the tracked registry. That's a Symfony 3/4-era package (lightSAML core 1.x). On Symfony 6/7 or PHP 8.2 you will spend day one fighting deprecations, not doing SSO.

Minimal Symfony bootstrap (if you go that path):

# config/packages/lightsaml_sp.yaml
lightsaml_sp:
    host: sp.example.com
    entity_id: https://sp.example.com/saml/metadata
    credentials:
        - certificate: '%kernel.project_dir%/var/certs/sp.crt'
          private_key: '%kernel.project_dir%/var/certs/sp.key'
    idp:
        corp:
            entity_id: https://idp.example.com/metadata
            single_sign_on_service:
                redirect: https://idp.example.com/sso/redirect
            certificate: '%kernel.project_dir%/var/certs/idp.crt'

Then import the bundle routing (@LightSamlSpBundle/Resources/config/routing.yml) to get the metadata endpoint, and confirm what actually got registered:

php bin/console debug:router | grep -i lightsaml
php bin/console debug:container lightsaml | head -40

Where to look first: the README's config reference (it is the documentation), then Resources/config/services.xml — that file tells you exactly which services the bundle gives you and is the blueprint for a Laravel port. First use case: SP-initiated SSO — build an AuthnRequest, redirect to the IdP, receive the POSTed SAMLResponse on your ACS route, validate the signature, pull NameID + attributes, log the user in.

Implementation Patterns

The bundle gives you builders, not a firewall. Unlike surfnet/stepup-saml-bundle, there is no security listener doing the work for you. The day-to-day pattern is a pair of controllers around the LightSAML profile builders:

// LoginController::login — SP-initiated SSO
$builder = $this->get('lightsaml.sp.builder'); // verify exact id via debug:container
$context = $builder->buildContext();
return $builder->buildAction()->execute($context); // 302 to the IdP
// AcsController::acs — POST binding, consumes SAMLResponse
$builder = $this->get('lightsaml.sp.response.builder');
$context = $builder->buildContext($request);   // pulls SAMLResponse + stored request state
$builder->buildAction()->execute($context);    // throws on signature/audience/time errors

$assertion = $context->getAssertion();
$nameId    = $assertion->getSubject()->getNameId()->getValue();
$email     = $this->attribute($assertion, 'urn:oid:0.9.2342.19200300.100.1.3');
// then authenticate locally (Auth::login() in Laravel, token storage in Symfony)

Request state lives in the session — implement it deliberately. The bundle ships a session-backed store for the AuthnRequest ID + relay state so the ACS can match the response to the request you sent. In Laravel this is the one class you must write: implement the LightSAML request-state storage interface on top of Session::put()/$request->session(), keyed by request ID, with a TTL. If you skip this, you lose replay/matching protection and every response looks "unmatched".

Metadata is the contract — serve it and pin it. Expose the generated metadata XML at a stable URL (e.g. /saml/metadata) and hand it to the IdP admin. Your entity_id, the <AssertionConsumerService Location>, and what the IdP has on file must be byte-comparable. Cache the XML (it changes only when certs rotate) and make sure the route is public — no auth middleware.

Attribute mapping belongs in one class. Don't scatter getAttribute() calls through controllers. Write a small SamlUserMapper that takes the assertion and returns an array/DTO (email, uid, displayName, groups), with configurable attribute names. Then JIT-provision: find-or-create the local user by NameID/email, and treat groups as the role source. This is the piece you will unit test, and it is the piece that breaks when an IdP changes its attribute release.

Multiple IdPs / discovery. Configure each IdP under an alias in the idp: map and carry the alias in relay state or a route parameter. The bundle's discovery controller lets users pick; for most Laravel ports a simple "which IdP?" screen or domain-based routing is less code and less fragile.

Skip SLO unless you must. Single Logout is where SAML integrations rot: partial logout, IdP-initiated logout callbacks, session ordering. Log out locally, redirect to the IdP's SLO URL best-effort, and don't fail the user's logout on an SLO error.

Testing. Unit-test the mapper with fixture assertions and test signature rejection with deliberately tampered XML. For integration, point at a throwaway IdP (samltest.id or a local SimpleSAMLphp) — do not develop against production Okta/Azure AD.

Gotchas and Tips

  • No Laravel support, at all. Every Symfony-ism in Resources/config/services.xml (tagged services, ContainerAware, parameter placeholders) needs translating. Budget a day for the port; it's small but not zero.
  • Staleness bites at install time. Run composer why-not lightsaml/sp-bundle on your PHP/Symfony version before promising anything. On PHP 8 you'll likely need lightsaml/lightsaml directly with your own wiring rather than the bundle.
  • Destination/ACS mismatch behind a proxy is the #1 false alarm. Symfony: enable use_proxy_vars or configure trusted proxies. Laravel: TrustProxies middleware — otherwise the SP thinks its ACS is http:// while the IdP sends https://, and validation fails with a Destination error.
  • Don't regenerate the session ID between the login redirect and the ACS. Laravel's session regeneration on login, or a fresh session from a load-balanced node without sticky sessions/shared session storage, produces "AuthnRequest not found in store". Also consider that users with blocked cookies simply cannot complete SSO — detect and show a friendly message.
  • CSRF and middleware. Exclude the ACS route from VerifyCsrfToken (it's a cross-site POST by design) and from auth. Keep it on web for the session.
  • Certificate formatting. Paste the IdP's PEM body (base64 between the BEGIN/END CERTIFICATE lines) exactly as the config expects; extra whitespace or a missing newline yields signature verification failures that read like "invalid signature" rather than "bad cert".
  • Clock skew. LightSAML enforces NotBefore / NotOnOrAfter; a minute of drift on the IdP gives "assertion is not yet valid". Keep SP and IdP on NTP.
  • Debug by decoding first, validating second. Log base64_decode($request->input('SAMLResponse')) before running validation, and correlate with the request ID you stored. LightSAML throws specific exceptions (LightSamlValidationException, XML parse errors) — log the raw XML alongside them or you'll be guessing.
  • Watch entity ID exactness. A trailing slash difference between metadata, config and the IdP record is the cause of most "Invalid issuer"/"Unknown entity" errors.
  • Sanitize relay state before redirecting to it — it's attacker-influenced and an easy open redirect.
  • Extension points (worth knowing if you port): swap the request-state storage service, swap the credential store (for key rotation), and decorate the profile builder to add logging or attribute enrichment. These three cover 90% of real-world customization.
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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast