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

Lightsaml Lightsaml Laravel Package

kidatsy/lightsaml-lightsaml

LightSAML is a PHP library for SAML 2.0, helping developers build service providers and identity providers with support for assertions, messages, metadata, signing, and encryption. A lightweight toolkit for adding SAML SSO to PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a fork of lightsaml/lightsaml published under a different Composer name (kidatsy/lightsaml-lightsaml). It is not on the well-trodden path: zero dependents, zero stars, last tag in May 2017, and the upstream project itself has moved on considerably since then. Before writing any code, verify what you actually pulled:

  1. Read composer.json — confirm the PSR-4 prefix is LightSaml\ and the PHP constraint. If it still says php: >=5.4 and you are on 8.x, expect deprecation noise (each(), dynamic properties, count() on non-countables) and test every flow early.
  2. Decide whether you should use lightsaml/lightsaml (the upstream) instead. Pin whichever you choose; do not use ^1.0 against a 2017 tag and assume stability.
  3. Install: composer require kidatsy/lightsaml-lightsaml, plus psr/log if it is not already pulled in. You need ext-dom, ext-openssl, and ext-libxml (for phpseclib/xmlseclibs-style canonicalisation).

Where to look first (in this order):

  • src/LightSaml/Model/Protocol/ — AuthnRequest, Response, LogoutRequest/Response, Status.
  • src/LightSaml/Model/Metadata/ — EntityDescriptor, SpSsoDescriptor, IdpSsoDescriptor, SingleSignOnService, AssertionConsumerService, KeyDescriptor.
  • src/LightSaml/Binding/ — BindingFactory, HttpRedirect, HttpPost, HttpArtifact.
  • src/LightSaml/Credential/ — X509Certificate, X509Credential, KeyHelper, Criteria/*.
  • src/LightSaml/Builder/Profile/ — the profile builders. Run grep -R "class .*ProfileBuilder" src/ before reading docs; class names drifted between LightSAML minor versions and the README lies more often than the source.

First use case — SP-initiated SSO. Wire up a credential store and entity descriptors, run the SP profile builder, and hand the resulting AuthnRequest to your front end:

use LightSaml\Credential\{X509Certificate, X509Credential, KeyHelper};
use LightSaml\Store\Credential\FixedCredentialStore;

$idpCred = new X509Credential(new X509Certificate($idpPem, false));
$idpCred->setEntityId('https://idp.example.com/metadata');

$spCred = new X509Credential(
    new X509Certificate($spCertPem, false),
    KeyHelper::createPrivateKey($spKeyPem, '', false)
);
$spCred->setEntityId('https://app.example.com/saml/metadata');

$creds = new FixedCredentialStore();
$creds->add($idpCred);
$creds->add($spCred);

Then build the profile context, attach the incoming HTTP request (setMethod, setQueryString, setContent), execute the action chain, and read $context->getOutboundContext()->getMessage() — that is your AuthnRequest. Serialise it with the binding from BindingFactory and redirect or auto-POST the user. That single round trip (send request → receive response → extract Assertion → read NameID) is 90% of real-world usage.

Implementation Patterns

Metadata as the source of truth. Prefer loading real IdP metadata XML (EntityDescriptor::loadXml($xml)) over hand-building descriptors. Validate validUntil and cache the parsed descriptor; the parse is not cheap and IdP metadata rarely changes. For your own SP metadata, generate it once with the metadata profile builder and serve it from a controller.

Two-store pattern. FixedEntityDescriptorStore (or FixedCredentialStore) is fine for one IdP. For multi-tenant or per-environment setups, implement EntityDescriptorStoreInterface / CredentialStoreInterface backed by your DB and resolve by entity ID. Never share a X509Credential object across trust boundaries — clone or build per entity.

Direction-specific profile builders. The library separates "receive" (IdP→SP response, or SP→IdP request) from "send". In practice you run:

  • SP outbound: build AuthnRequest, set Issuer, Destination, AssertionConsumerServiceURL, ProtocolBinding, NameIDPolicy, ID (Helper::generateId()), IssueInstant. Persist the ID and RelayState in the session.
  • SP inbound: pass the raw POST body into $context->getHttpRequest()->setContent(...), let the binding decode, then run the action chain. On success pull the Assertion from $context->getInboundContext()->getMessage() (a Response) via getAssertions().
  • IdP side: mirror image — receive AuthnRequest, resolve the user, construct Response with a Status, a Subject/NameID, Conditions (NotBefore/NotOnOrAfter), AuthnStatement, and optionally AttributeStatement.

Bindings. Use BindingFactory::getBinding(SamlConstants::BINDING_SAML2_HTTP_POST) for the response path (base64 in a form field) and ..._HTTP_REDIRECT for the request path (DEFLATE + base64 + URL-encode). Do not hand-encode; the binding classes handle signature parameter placement (SigAlg, Signature) and canonicalisation.

Custom actions instead of forking. Both ProfileBuilder and the action chain are composable. If you need post-validation hooks (just-in-time user provisioning, audit logging, attribute mapping), implement LightSaml\Action\ActionInterface and slot it in, or decorate the builder. This is safer than editing vendor code that you will never be able to upgrade.

Testing. Snapshot XML in/out of each model (AuthnRequest, Response, Assertion) and round-trip it. Generate throwaway certs with openssl req -x509 -newkey rsa:2048 -nodes and assert both the happy path and a tampered-assertion rejection. If a test only checks "no exception", it is not testing SAML.

Gotchas and Tips

  • The fork itself is the biggest gotcha. kidatsy/lightsaml-lightsaml is not lightsaml/lightsaml; your composer.json will look wrong to anyone reading it, and Packagist metadata for forks is routinely stale. If you must use it, add a repositories entry pointing at the VCS URL and a comment explaining why. Otherwise use upstream or onelogin/php-saml / simplesamlphp.
  • Raw body, not reconstructed XML. Signature validation runs over the exact bytes the IdP signed. If you pull $request->input('SAMLResponse'), base64-decode, and re-serialise via DOMDocument, whitespace and namespace prefixes can shift and every signature fails with a generic "invalid signature". Always feed the binding the original POST body.
  • Entity ID exactness. Trailing slash, case, and http vs https mismatches between your metadata and the IdP's config produce opaque InvalidIssuer/Destination errors. Log both sides’ entity IDs when debugging.
  • Clock skew. NotBefore/NotOnOrAfter and IssueInstant checks are strict. Configure TrustOptions (allow unsigned assertions/requests where your IdP requires it) and check server NTP. A two-minute drift is a classic "works locally, fails in prod".
  • InResponseTo is your CSRF defence. Store the outbound AuthnRequest ID and validate the response's InResponseTo against it, plus RelayState. The library will not do session state management for you.
  • Certificates: X509Certificate wants PEM including the -----BEGIN CERTIFICATE----- lines. KeyHelper::createPrivateKey($pem, $passphrase, $isFile) — passing false for $isFile when you supply a path is a silent failure generator.
  • ID generation. Helper::generateId() produces an NCName-safe string. If you roll your own, IDs starting with a digit get rejected by strict IdPs.
  • Logging is the only debugger. Actions implement LoggerAwareAction; attach a PSR-3 logger to the builder before execute(). Without it, validation failures surface as LightSamlValidationException with almost no context.
  • Encrypted assertions are the least-tested corner. Verify with the actual IdP early — many implementations silently fall back to plaintext, hiding the bug until a security review.
  • Extension points worth knowing: CredentialStoreInterface, EntityDescriptorStoreInterface, TrustOptions, MetadataFilter, and the ActionInterface chain. These are the supported seams; subclassing concrete actions is not.
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.
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
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle