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

Oneloginsaml Bundle Laravel Package

bloomatwork/oneloginsaml-bundle

A Symfony bundle that integrates the OneLogin SAML PHP toolkit, adding SAML 2.0 single sign-on authentication to Symfony applications. It helps configure service provider settings, handle SAML requests and responses, and authenticate users via an identity provider.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the framework reality check. bloomatwork/oneloginsaml-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/onelogin_saml.php. You cannot composer require it into a Laravel app and expect it to boot — its public surface is a Bundle subclass, a DependencyInjection extension, and a SecurityBundle firewall factory. So "getting started" for a Laravel developer means deciding what you actually adopt:

  1. Adopt the underlying library, not the bundle. The bundle is thin glue over onelogin/php-saml, which is framework-agnostic and perfectly usable in Laravel. Run composer require onelogin/php-saml and wire it yourself — this is the path that matches the bundle's own architecture without dragging in Symfony.
  2. Read the bundle as a reference implementation. Before writing your own glue, read three files in the repo: DependencyInjection/Configuration.php (the exact settings tree — SP entity ID, ACS URL, IdP certs, baseurl), Security/Authentication/Provider/OneloginSamlProvider (how the SAML response becomes a token/user), and the shipped controller for the ACS and metadata endpoints. That's essentially the spec for what you'll reimplement as a Laravel controller + middleware.
  3. Check the health of the dependency chain. Score 0, 0 dependents, Symfony 2.x/3.x era, extends the legacy Bundle class. Treat this repo as a snapshot of an approach, not a maintained dependency. Verify the onelogin/php-saml version referenced in its composer.json and cross-check that version's CVE history before committing.

Minimal first use case (SP-initiated login in Laravel):

  • Configure OneLogin_Saml2_Auth with an SP + IdP settings array (entity ID, ACS URL, IdP SSO URL, X.509 signing cert). Keep this array in config/saml.php and env vars — not hardcoded.
  • Add two routes: GET /saml/login → $auth->login() (redirect to IdP), and POST /saml/acs → $auth->processResponse() then Auth::login($user).
  • Add GET /saml/metadata returning $auth->getSettings()->getSPMetadata() so your IdP admin can register you.
  • Add GET /saml/logout → $auth->logout() if you need SLO.

Once that round-trip works — protected route → IdP redirect → ACS POST → authenticated session — everything else (IdP-initiated, logout, attribute mapping, multi-tenant) is incremental.

Where to look first: the bundle's Configuration.php for the settings keys, the README for the YAML example (translate it 1:1 into a PHP array), and onelogin/php-saml's own settings_example.php in its repo — that's the authoritative source for what the settings array must contain.

Implementation Patterns

The user-mapping seam is yours to own. The Symfony bundle ships a SamlUserFactory interface precisely because the SAML response → application User conversion is app-specific. In Laravel the equivalent is a dedicated service, e.g. App\Services\Saml\UserProvisioner, invoked from the ACS controller:

public function provision(array $attributes, string $nameId): User
{
    $email = $attributes['mail'][0]
        ?? $attributes['emailaddress'][0]
        ?? $attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'][0]
        ?? throw new SamlAttributeException('No email attribute in assertion');

    $user = User::firstOrNew(['email' => $email]);
    $user->name ??= $attributes['displayName'][0] ?? $email;
    $user->saml_name_id = $nameId;
    $user->save();

    return $user;
}

Keep the attribute-name map in config (config/saml.php → attribute_map), not in code. IdPs disagree wildly on mail vs emailaddress vs a full SOAP namespace URI — this is the single biggest source of "works with Okta, breaks with Entra" bugs.

JIT provisioning vs. lookup-only. For internal apps, firstOrNew above (just-in-time provisioning) is the pragmatic default and the bundle's provider pattern supports it. For anything sensitive, do lookup-only and fail closed — an unknown IdP user must not self-register into your app just because the IdP authenticated them. Make this a config flag, not a code fork.

Both flow directions. SP-initiated is the normal redirect dance. IdP-initiated (user clicks the app tile in Okta) POSTs straight to your ACS with no RelayState / in-flight AuthnRequest. Test both explicitly — teams routinely ship SP-initiated and discover IdP-initiated is broken in production. For IdP-initiated, set an explicit default landing route rather than depending on RelayState being present.

Logout: local-first. SAML SLO is brittle and depends on the IdP's SLO endpoint behaving. Many teams do local logout + redirect to the IdP's logout URL and treat federated SLO as best-effort. In the Symfony bundle this maps to logout.success_handler; in Laravel it's your LogoutController deciding between Auth::logout() + redirect vs. $auth->logout().

Testing: never hit a real IdP in CI. Capture one real signed SAML response as a fixture, then inject it into processResponse() (or POST it to the ACS route) in feature tests. Wrap the toolkit behind a small SamlAuthenticatorInterface of your own so you can swap to a maintained Laravel SAML package later without touching controllers — this is exactly the decoupling the Symfony bundle almost provides and you should provide deliberately.

Metadata as a config artifact. Serve /saml/metadata for initial IdP registration, but store the IdP's metadata XML in your repo or config store so certificate rotation is a config change and a deploy, not a code change.

Gotchas and Tips

  • This is not a Laravel package. Repeating because it's the highest-cost mistake: no service provider means no php artisan vendor:publish, no auto-registered routes, no container bindings. Any tutorial you find for this bundle will be Symfony-shaped (AppKernel, security.yaml, onelogin_saml:). Translate the concepts, not the configuration.
  • Abandonment and supply-chain risk. 0 stars, 0 dependents, Symfony 2.x/3.x vintage. If you fork it or copy from it, you own it. Prefer the framework-agnostic onelogin/php-saml (actively maintained) and, if you ever move to Symfony, hslavich/OneloginSamlBundle or nbgrp/onelogin-saml-bundle. Pin the toolkit version and watch its CVE feed.
  • Certificate format is a trap. The OneLogin toolkit wants the raw base64 body of the cert (no -----BEGIN CERTIFICATE----- headers, no newlines) for most config keys — but some keys expect full PEM. Getting this wrong produces "invalid signature" errors, not "bad certificate", which sends you debugging the wrong layer. Copy the format from the toolkit's settings_example.php verbatim.
  • Audience / recipient mismatch. sp.entityId and sp.assertionConsumerService.url must match exactly what's registered at the IdP — trailing slash, http vs https, port. This is the most common "works on my machine" failure. Compare the assertion's <Audience> and <Recipient> against your config character by character.
  • Clock skew. Assertions carry NotBefore / NotOnOrAfter. A few seconds of drift between IdP and SP throws OneLogin_Saml2_ValidationError. Ensure NTP is synced on both boxes and consider a small skew allowance in toolkit settings.
  • Attribute namespacing. Attributes arrive as arrays keyed either by friendly name (mail) or OID (urn:oid:0.9.2342...) or full URI. Always isset($attributes[$key][0]), never assume a scalar. Log the full $attributes dump once during setup (with debug: true in toolkit settings) to see what your IdP actually sends, then turn debug off.
  • baseurl behind a proxy / subpath. The toolkit builds ACS and SLO URLs from config. Behind a load balancer, reverse proxy, or subdirectory mount, set the base URL explicitly or the ACS URL in the assertion won't match. In Laravel, also ensure TrustProxies is configured — otherwise url() helpers generate the wrong scheme/host in redirects.
  • SameSite cookie kills the return POST. SAML bounces through the IdP and comes back as a cross-site POST. SameSite=Strict on the session cookie drops it, and you land on the ACS unauthenticated. Use Lax (or None + Secure) for the session cookie and confirm RelayState survives the round-trip.
  • CSRF and the ACS endpoint. The ACS is a POST from a third party — it must be excluded from CSRF verification (app/Http/Middleware/VerifyCsrfToken::$except). Also exempt it from any CSP that blocks form posts, and keep WAFs from body-inspecting and re-encoding the assertion (whitespace changes break canonicalization and thus signature validation).
  • Debugging workflow. Set debug: true, then read getLastErrorReason() and getLastErrorException() — that pair is usually enough to distinguish signature vs. audience vs. recipient failures. Never leave debug on in production: it writes full assertions (containing PII and session identifiers) to logs.
  • Extension point if you outgrow the toolkit's default validation. The bundle's authenticator is thin; the same is true of your controller. Fork at the response-validation step if you need extra audience checks, attribute-based authorization, or replay protection (cache assertion IDs and reject duplicates) — wire ReplayCache / a cache store if your php-saml version supports it. Replay protection is genuinely worth implementing for anything customer-facing.
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.
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin