ziffmedia/laravel-onelogin
OneLogin SAML single sign-on for Laravel. This package provides a simple, configurable integration for OneLogin authentication, handling SAML responses, login and logout flows, and user provisioning so you can add enterprise SSO to your Laravel app with minimal setup.
The package wraps onelogin/php-saml and gives you a ready-made SAML service provider (SP): routes, a controller, config, and a trait for turning SAML attributes into an authenticated Laravel user.
Install and publish config
composer require ziffmedia/laravel-onelogin
php artisan vendor:publish --tag=onelogin-config
Fill in the IdP details in config/onelogin.php (or via .env). At minimum you need the IdP entity ID, SSO URL, and the IdP signing certificate. The SP side needs an entity ID and an ACS URL pointing at the package's callback:
ONELOGIN_IDP_ENTITY_ID=https://yourorg.onelogin.com/trust/saml2/http-post/sso/xxxx
ONELOGIN_IDP_SSO_URL=https://yourorg.onelogin.com/trust/saml2/http-post/sso/xxxx
ONELOGIN_IDP_SLO_URL=https://yourorg.onelogin.com/trust/saml2/http-get/slo/xxxx
ONELOGIN_IDP_X509_CERT="-----BEGIN CERTIFICATE-----..."
ONELOGIN_SP_ENTITY_ID=https://app.example.com
ONELOGIN_SP_ACS_URL=https://app.example.com/onelogin/acs
Add the trait to your User model
use ZiffMedia\LaravelOneLogin\OneLoginAuthenticatable;
class User extends Authenticatable
{
use OneLoginAuthenticatable;
}
First use case: drop the IdP metadata URL (/onelogin/metadata) into OneLogin's app configuration, then hit /onelogin/login in the browser. The package redirects to the IdP, receives the assertion at /onelogin/acs, resolves the user via the trait, and logs them in through Laravel's guard.
Look first at: the published config file, the registered routes (route:list | grep onelogin), and the trait — those are the three extension points you will actually touch.
Protecting the app. Keep using Laravel's normal auth middleware; the package only handles how the user gets logged in. Put the OneLogin login route on your own "Sign in" page rather than relying on the package's default redirect:
Route::get('/login', fn () => redirect()->route('onelogin.login'))->name('login');
User provisioning. The idiomatic pattern is "find or create by SAML NameID/email" inside the trait. Override the lookup so you control which attribute is the key and what happens on first login:
public function resolveOneLoginUser(array $attributes): ?self
{
return static::firstOrCreate(
['email' => $attributes['email']],
['name' => $attributes['name'] ?? $attributes['email']],
);
}
If you don't want auto-provisioning (e.g., HR-driven accounts), return null for unknown users and the login will fail cleanly — better than silently creating accounts.
Attribute mapping. IdP-facing attribute names (urn:oid:..., http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress, or friendly names) vary per IdP. Map them in one place (config or trait) so the rest of the app never sees raw SAML keys. Log the raw $attributes on first integration so you can see exactly what your IdP sends.
Logout / SLO. Use the package's logout route for signing out. SLO (single logout) requires the IdP's SLO URL and a public SP SLO endpoint; if the IdP is slow or misconfigured, SLO will hang. Consider doing a local Auth::logout() + session invalidation first, then redirect to SLO, so the local session is never left dangling.
Programmatic auth and testing. Wrap the redirect in your own controller so tests can assert on the route name; stub the SAML layer (or point at a test IdP) rather than mocking the trait. For feature tests, bypass SAML with $this->actingAs($user) — the package only matters on the login boundary, not on every request.
SP signing. If you need signed requests or encrypted assertions, generate an SP keypair and register the certificate with OneLogin. The IdP cert is for verifying responses; the SP key is for signing requests — don't mix them up.
http vs https, or a different host (www. vs apex) between the value registered at the IdP and the generated ACS URL produces "invalid signature" or "audience mismatch" errors that look like cert problems. Check the actual URL the package generates first.http:// ACS URLs. Configure TrustProxies (or set APP_URL correctly); the SP entity ID and ACS URL are derived from the request in many setups.onelogin/php-saml toolchain wants either a raw base64 body or a full PEM block depending on config key. If you get "certificate not found," try both — and strip Windows line endings from .env values (\r breaks cert parsing).NotBefore/NotOnOrAfter. Container clocks drifting a few minutes cause intermittent "assertion expired" errors. Keep NTP running, and know the php-saml setting for allowed clock skew if you need it.php artisan config:cache and route:cache will freeze the SAML config and routes. Republish/clear both after changing IdP settings — a stale cached config is the most common "I updated the cert but nothing changed" cause.Auth::logout() and invalidates the session, or users can hit Back and remain logged in.SESSION_LIFETIME if you want users re-authenticated more often than the IdP's own session policy.Auth::loginUsingId() route guarded by app()->isLocal(), or a seeded user plus actingAs in tests.AuthnRequest, multi-tenant IdPs — you're better off using the underlying onelogin/php-saml directly rather than fighting the wrapper.How can I help you explore Laravel packages today?