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

Php Saml Laravel Package

onelogin/php-saml

onelogin/php-saml adds SAML 2.0 SSO support to PHP applications, including SP- and IdP-initiated login, signed assertions, logout handling, strict mode, and configurable security checks. The 4.x branch supports PHP 7.3+ and PHP 8.x.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. onelogin/php-saml is a framework-agnostic SAML 2.0 SP toolkit, not a Laravel package. It provides the hard parts of the protocol — AuthnRequest construction, Response/Assertion signature and decryption validation, metadata generation and parsing, SLO message handling — while deliberately delegating session state and user persistence to the host app. That is the right seam for Laravel: we keep Eloquent users, guards, and policies, and use the library purely as a protocol engine behind our own controller and guard. The cost is that we own the integration layer: routing, CSRF exemptions, config assembly, replay cache, attribute mapping, and user provisioning are all ours to build. There is no Laravel service provider, facade, or config stub shipped upstream.

Integration feasibility. Technically straightforward. Settings are passed as a plain PHP array to the Auth constructor, which maps cleanly onto config/saml.php + env vars and survives config:cache. The three logical endpoints (metadata, ACS, SLS) map to three named routes. The main friction points:

  • Non-PSR-4 class names. The 4.x branch retains underscore-style global classes (OneLogin_Saml2_Utils::getSelfURLNoQuery(), OneLogin\Saml2\Auth). Composer autoloading works, but the container binding, IDE support, and mocking story is worse than a modern namespaced package. We should wrap it behind our own SamlProvider interface from day one rather than calling Auth directly from controllers.
  • Session coupling. Request IDs for InResponseTo validation live in the session. On multi-node deployments without a shared session store this breaks silently between the redirect and the POST-back.
  • The certs/ and settings.php defaults. The README explicitly warns that files placed under vendor/onelogin/php-saml are destroyed by composer update. Certificates must live in storage/app/saml (or a secrets manager), never in vendor or config/.
  • CSRF. The ACS POST arrives from the IdP with no CSRF token. It must be explicitly exempted (VerifyCsrfToken::$except pre-Laravel 11, validateCsrfTokens()->except() in Laravel 11/12). This is a one-line change but is a common source of "works locally, 419 in staging" incidents.

Technical risk. Moderate, and concentrated in security configuration rather than the library itself.

  • Misconfiguration is the dominant risk, not code defects. The README mandates strict: true, non-SHA-1 signatureAlgorithm/digestAlgorithm, and IdP certificate registration rather than fingerprint comparison. Any of these left at defaults is a production vulnerability that will not surface in functional testing. This needs a config validation test in CI, not a code review.
  • Unsolicited responses and replay. rejectUnsolicitedResponsesWithInResponseTo and destinationStrictlyMatches default to disabled and must be turned on deliberately. Replay protection is explicitly not provided — the library only exposes getLastMessageId() / getLastAssertionId() so we can implement a cache-backed dedupe. That is our control to build and operate.
  • Transitive dependency exposure. xmlseclibs carries the real CVE history (CVE-2019-3465, CVE-2016-1000253 signature wrapping, and the most recent CVE-2025-66475 patched in 2.21.1). Our exposure is therefore driven by a transitive package's release cadence as much as this one's.
  • Maintainer concentration. Effectively a single-maintainer project under the SAML-Toolkits org. Release cadence is event-driven (security patches) rather than planned. Low bus factor, but 1.3k stars and heavy transitive adoption by other PHP SAML plugins means vulnerabilities get found and patched quickly — the ecosystem is watching it.
  • "Dependents: 0" is a metadata artifact, not a signal of abandonment; Packagist download counts and the fact that most PHP SAML plugins wrap this library tell the real story.

Key questions to resolve before committing:

  1. Which IdPs must we support at launch, and does each one sign the Response, the Assertion, or both? Mixed signing models are the most common source of "works for Okta, fails for Entra ID."
  2. Do any customers require encrypted assertions, and do they require SP-initiated Single Logout? SLO support is inconsistent across IdPs (notably limited in Microsoft Entra ID) and is where most of the integration effort actually lands.
  3. Is IdP-initiated (unsolicited) SSO a requirement from any prospect? If yes, we cannot enable rejectUnsolicitedResponsesWithInResponseTo, which materially weakens replay posture and requires an alternative control.
  4. Multi-tenant or single-IdP? One IdP per deployment is a two-day config task; per-tenant IdPs mean per-tenant settings resolution, cert storage, and metadata endpoints — a different design.
  5. Is JIT user provisioning acceptable, or must accounts be pre-provisioned by SCIM or admin action? This determines whether we can ship without an admin-side account linking flow.
  6. What is our NameID and attribute contract with each IdP, and who owns the mapping when a customer's directory is non-standard?

Verdict: sound choice. It is the de facto standard PHP SAML toolkit and the alternative (writing SAML validation ourselves, or adopting SimpleSAMLphp as a separate service) is worse on both risk and effort. Approve, but budget explicitly for the wrapper layer and security hardening rather than treating it as a drop-in package.

Integration Approach

Stack fit. Requires PHP ≥ 7.3 on the 4.x branch (PHP 8.x supported), which is satisfied by any Laravel 9+ application. It has no Laravel-version coupling whatsoever, so it will not block framework upgrades — a meaningful advantage over the abandoned aacotroneo/laravel-saml2 wrapper, which has historically lagged both Laravel and php-saml releases. Install with composer require onelogin/php-saml:^4.0 and pin to a caret range, not dev-master.

Recommended shape. Keep the vendor library at arm's length:

  • config/saml.php — env-driven, one array per IdP (or per tenant), including strict, algorithms, certs, and endpoint URLs. Must be compatible with config:cache (no closures, no runtime lookups).
  • app/Services/Saml/SamlProviderFactory.php — builds a configured OneLogin\Saml2\Auth from a settings array; the only place in the codebase that instantiates vendor classes. Bind to an interface so tests can fake it.
  • app/Http/Controllers/SamlController.php — login, acs, sls, metadata actions, each thin: delegate to the provider, translate results into Laravel auth events.
  • app/Services/Saml/SamlUserResolver.php — maps NameID + attributes to an Eloquent user, applies JIT provisioning or rejects, then Auth::login($user, remember: false) and session()->regenerate().
  • app/Services/Saml/ReplayGuard.php — cache-backed set of processed message/assertion IDs keyed with TTL derived from NotOnOrAfter, using the shared cache store (Redis), not the array driver.

Migration path. If a SAML integration already exists via aacotroneo/laravel-saml2 or 24slides/laravel-saml2, both are wrappers over this same library, so the migration is largely a de-wrapping exercise: lift the settings array out of the wrapper's config, move certificate paths into storage, and replace the wrapper's routes with our own controller. User records and NameID mappings carry over unchanged. If migrating from a Socialite-based OIDC flow, there is no shortcut — SAML is a different protocol and the flows do not share code.

Compatibility considerations.

  • Laravel Octane: the toolkit is stateless per request, so it is compatible, but audit that no settings state is cached in static properties across requests. Safe default: construct Auth per request (cost is negligible) rather than resolving it as a singleton.
  • Load balancers / proxies: getSelfURLNoQuery() derives the ACS URL from request headers. Behind a proxy, TrustProxies must be configured correctly or Destination validation will fail. Prefer hardcoding sp.assertionConsumerService.url in settings over URL auto-detection.
  • WAF / body size: corporate IdPs can emit multi-KB base64 responses; encrypted assertions inflate further. Verify WAF rules and post_max_size before go-live, not during the customer's first login attempt.
  • Encrypted assertions require openssl (the old mcrypt requirement is legacy 2.x guidance and should be ignored); confirm the SP private key is available to the app at runtime and is not committed.
  • SAML 2.0 only. No OIDC, no WS-Fed. If a prospect runs ADFS in WS-Fed mode, this package does not help.

Sequencing.

  1. Spike (2–3 days). Stand up one IdP (use a free OneLogin or Okta developer tenant) against a Laravel skeleton; validate strict mode, SHA-256, signed assertion, and a login round-trip. Output: a hardened reference config/saml.php.
  2. Wrapper layer. Provider interface, factory, replay guard, config validation test. Land this before any customer config exists.
  3. Happy path. Login → ACS → user resolve → session. Include signed metadata publishing so customer IT can onboard without hand-editing XML.
  4. Hardening. Replay cache, RelayState allowlist (open-redirect prevention is explicitly the SP's responsibility), negative-path tests (expired assertion, wrong audience, wrong destination, tampered signature, replayed assertion), structured logging with request IDs.
  5. SLO. Only after a specific IdP's SLO behavior is confirmed — this is the highest-variance piece and should be scoped separately.
  6. Multi-tenant (if required). Per-tenant settings resolution, cert provisioning, tenant-scoped metadata and ACS URLs.
  7. External review. A focused pen test or security review of the ACS path before GA. Given the CVE history around signature wrapping, this is not optional.

Realistic estimate for a single-IdP, single-tenant integration with JIT provisioning: 1–2 weeks for a mid-level Laravel developer, assuming IdP test credentials are available on day one. Multi-tenant plus SLO: 4–6 weeks. The dominant schedule risk is IdP-side configuration turnaround with customer IT, not our engineering.

Operational Impact

Maintenance. Low-to-moderate, but with a hard floor: security patch tracking is mandatory, not discretionary. Our update trigger is twofold — this package's releases and, more often, xmlseclibs advisories. Add Dependabot/Renovate with auto-PR for patch versions, a monthly review cadence, and a named owner. Because the release cadence is event-driven and the maintainer is essentially one person, we should be prepared to patch by pinning a specific commit if a CVE lands and a tagged release lags. Keep the wrapper interface thin enough that swapping the protocol engine is a contained change, not a rewrite.

Support. No commercial support tier, no SLA. Community support is via GitHub issues. For an enterprise-facing SSO feature this means we are the tier-1 and tier-2 support for SAML — and SAML failures arrive as "I can't log in," which is a P1 by default. Budget for:

  • A runbook covering the top failure modes below, written for whoever is on call.
  • A diagnostic path that captures the SAML response ID and error reason server-side without logging full assertions (PII, and a token replay risk if logs are broadly readable). Log the message ID, issuer, NameID hash, and validation failure reason only.
  • A documented break-glass path: if SAML breaks, can an admin still reach the account through password or an admin-initiated reset? Answer this before launch.

Scaling. The library is not a scaling concern. Signature verification is a single RSA operation per login — sub-10ms — and SSO traffic is bounded by human login rates, not API volume. No horizontal scaling issues, no state beyond the session and the replay cache. The two scaling-adjacent items:

  • Shared session store is required for any multi-node deployment; request-ID validation fails without it.
  • IdP metadata fetching uses curl and must never happen on the request path. Pull metadata on a scheduled job, diff it, alert on certificate or endpoint changes, and require human approval to apply — silent auto-apply of a changed IdP certificate defeats the trust model.

Failure modes to design and alert for.

  • Certificate expiry. SP and IdP certs both expire. This is the single most common cause of a total SSO outage, and it fails hard with a confusing error. Automated expiry monitoring at 30/14/7 days, and a documented key-rollover procedure using the sp_new.crt mechanism the toolkit supports.
  • Clock skew. NotBefore/NotOnOrAfter validation fails if NTP drifts. Alert on host clock offset; know the allowed skew in the settings.
  • Session loss between redirect and POST-back. Users on a different node, an expired session cookie, or SameSite policy on the IdP-initiated round trip produce a generic failure. Needs explicit error messaging.
  • RelayState mishandling. Either an open-redirect vulnerability (if used unvalidated) or a broken return-to-page experience. Enforce an allowlist of internal paths.
  • IdP-side config drift. Customer IT rotates a cert or changes the ACS URL; every login for that tenant fails simultaneously. Metadata diffing and per-tenant health checks catch this before the customer calls.
  • Unsolicited-response rejection. If any IdP is configured for IdP-initiated flow while rejectUnsolicitedResponsesWithInResponseTo is on, those users fail with no obvious cause. This must be a per-IdP setting, not a global one.
  • Partial logout. SLO frequently logs the user out of the app but not the IdP, or vice versa, producing confusing re-login loops. Set expectations with customers: local logout works reliably; full SLO depends on their IdP.
  • WAF or body-size rejection of the ACS POST, which presents as a 403/413 rather than an auth error — easy to misdiagnose.

Ramp-up. The library's API is learnable in a day; SAML itself is not. The real ramp-up cost is protocol literacy: AuthnRequest/Response/Assertion structure, HTTP-Redirect vs HTTP-POST bindings, what "signed assertion but unsigned response" implies, and why Destination and Audience validation matter. A developer new to SAML should be given the spike task with a real IdP tenant, not a mocked one. Plan 3–5 days of genuine learning curve on top of the integration estimate, and ensure at least two engineers touch the ACS path so this is not a single-person knowledge silo. Onboarding a new IdP once the wrapper exists should drop to a few hours of configuration, which is the metric to hold the design to.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings