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

Shibboleth Bundle Laravel Package

kuleuven/shibboleth-bundle

A Symfony bundle that adds Shibboleth single sign-on authentication to your application, handling service provider setup, attribute mapping, and user sessions so you can integrate institutional SSO with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites. This bundle is not a Shibboleth Service Provider — it is only the glue between Symfony's security layer and the mod_shib Apache module. You need:

  • Apache (or another web server) with mod_shib installed and a working shibboleth2.xml / federation metadata pointing at one or more IdPs.
  • PHP receiving the Shibboleth attributes into $_SERVER (typically Shib-Session-ID, Shib-Application-ID, Shib-Identity-Provider, eppn, REMOTE_USER, plus any released attributes).
  • PHP 5.x/7.x and Symfony 2.x (the 2016-era release line this bundle targets). See Gotchas before assuming it drops into a modern Symfony app.

Install and enable.

composer require kuleuven/shibboleth-bundle
// app/AppKernel.php
$bundles[] = new Kuleuven\ShibbolethBundle\KuleuvenShibbolethBundle();

Minimal config. The only setting you almost always touch is which $_SERVER key holds the stable user identifier:

# app/config/config.yml
shibboleth:
    uid_attribute: eppn   # or uid, persistent-id, REMOTE_USER, mail, ...

Wire the firewall. The bundle exposes a shibboleth: true firewall flag:

# app/config/security.yml
security:
    providers:
        shibboleth:
            id: app.shibboleth_user_provider   # your implementation
    firewalls:
        main:
            pattern: ^/
            provider: shibboleth
            shibboleth: true
            logout:
                path: /logout
                handlers: [kuleuven.shibboleth.logout_handler]

You supply a UserProviderInterface implementation that turns the uid (e.g. [email protected]) into your application User object.

First use case to validate end-to-end. Protect a single route and hit it from a browser that has an active Shibboleth session. If $_SERVER['Shib-Session-ID'] is set and uid_attribute resolves, the bundle's listener should build a ShibbolethToken, hand it to your provider, and place an authenticated token in the firewall. If it does not, the problem is almost always upstream (mod_shib not running, attribute not released, wrong key name) rather than the bundle.

Where to look first when reading the source. Security/Firewall/ (the listener), Security/Authentication/ (provider + tokens), Security/User/ (the user provider contract and any abstract base), DependencyInjection/Configuration.php (the real config surface), and the Twig extension (for the helper functions below). Those five files tell you everything the bundle actually does.

Implementation Patterns

Custom user provider is the integration seam. The bundle authenticates an identity; it does not own your user table. Implement the Symfony UserProviderInterface (in this Symfony generation that's loadUserByUsername($uid), refreshUser(), supportsClass()) and either auto-provision on first login or reject unknown uids:

public function loadUserByUsername($uid)
{
    $user = $this->em->getRepository(User::class)->findOneBy(['shibbolethUid' => $uid]);
    if (!$user) {
        // JIT provisioning from attributes, or throw UsernameNotFoundException
    }
    return $user;
}

If the bundle ships an abstract base provider, extend it so you inherit uid normalization and role mapping; only override the persistence lookup.

Gate UI on session state with the Twig helpers.

{% if shibboleth_session_active() %}
    Signed in as {{ app.user.username }} — <a href="{{ path('logout') }}">Sign out</a>
{% else %}
    <a href="{{ shibboleth_session_initiator_url }}">Log in via your institution</a>
{% endif %}

shibboleth_session_active() is a cheap check for Shib-Session-ID; shibboleth_session_initiator_url points the user at /Shibboleth.sso/Login with a return target. Together they let you render an institution chooser page without forcing a redirect.

Stateless vs. session firewalls. For pure SSO, stateless: false with a normal Symfony session is the common setup — the listener authenticates once per browser session. stateless: true works for API-style consumption but means no logout handler runs and every request must carry a live Shibboleth session. Pick deliberately; mixing the two on one firewall causes confusing "logged in but no user" behaviour.

Coexist with form login. Run two firewalls: a form_login firewall for local admin accounts and a shibboleth firewall (or the same firewall with both authenticators, ordered so Shibboleth runs first) for federated users. Guard with pattern: so /admin never falls into the Shibboleth firewall, otherwise an IdP-less admin is bounced to /Shibboleth.sso/Login and gets a 500 from mod_shib.

Logout. Always attach the bundle's logout handler if you want the local Symfony session destroyed. Shibboleth's own logout (/Shibboleth.sso/Logout) is a separate, IdP-dependent flow; drive it from your controller with a redirect if you need single logout, and accept that many IdPs do not support SLO.

Consume attributes beyond the uid. After authentication you generally need mail, displayName, schacHomeOrganization, group/entitlement attributes. Read them from $_SERVER in a request listener or from the token's attribute bag if the bundle populates one, and persist only what you need — attributes can change between logins.

Testing hooks. Write a functional test that fakes the SP by setting server vars on the test request:

$client->request('GET', '/', [], [], [
    'Shib-Session-ID' => '_abc123',
    'Shib-Application-ID' => 'default',
    'eppn' => '[email protected]',
]);

This is the fastest way to exercise the whole listener/provider path without Apache. Keep a fixture map of realistic attribute sets (staff, student, external) and assert role mapping from each.

Gotchas and Tips

It is effectively abandoned for modern Symfony. Last release Nov 2016, zero dependents. The 2.x security APIs it relies on (loadUserByUsername, UsernamePasswordToken, getUsername(), non-autowired service definitions, security.firewalls.*.shibboleth) were removed or renamed in Symfony 4/5. On Symfony ≥4 you will spend more time shimming the bundle than writing the equivalent listener. Realistic options: fork and port it, or read Shib-Session-Id yourself in a small RequestListener/custom authenticator. Treat the bundle as a reference implementation.

Never trust Shib-* headers unless Apache guarantees them. If the app is reachable directly or via a proxy that forwards client headers, an attacker can send Shib-Session-ID: x and eppn: admin@… and be authenticated. Hard requirements: mod_shib must terminate the request, incoming Shib-* headers must be stripped (RequestHeader unset Shib-Session-ID etc. in the vhost), and UseCanonicalName/proxy trust must be configured. Document this in your deployment notes — it is the single most common way this setup is broken in production.

Attribute key naming is environment-dependent. Depending on Apache/PHP SAPI versions you may see Shib-Session-ID (dashes preserved, env var) or HTTP_SHIB_SESSION_ID (header form) or REDIRECT_Shib-Session-ID after rewrite rules. Dump array_keys($_SERVER) filtered by /shib|eppn|uid|REMOTE_USER/i on the protected path and align uid_attribute to what is actually there. Attribute names are also case-sensitive and IdP-specific.

eppn is not always released, and is not always stable. Some IdPs release persistent-id, some only eduPersonTargetedID, some only mail. Design your user table around a chosen identifier and provide a fallback chain (or refuse to authenticate) — do not silently key users on mail, which changes.

Logout is not global by default. Clearing the Symfony session leaves the Shibboleth SP session intact, so the next request re-authenticates silently and the user appears "still logged in". If that matters, redirect through /Shibboleth.sso/Logout?return=<url> after local logout.

Debugging checklist. (1) phpinfo() on a Shibboleth-protected path confirms attributes reach PHP. (2) Shib-Application-ID present means mod_shib matched the request. (3) Shib-Identity-Provider tells you which IdP answered. (4) A 500 from /Shibboleth.sso/Login is mod_shib config, not Symfony. (5) Enable the bundle's logger channel if present; otherwise log the resolved uid in your provider.

Config quirks. Keep uid_attribute in sync with the vhost's Shibboleth.sso attribute mapping — if the IdP renames an attribute in metadata, this config silently stops matching and every login fails with "user not found" rather than a config error. Add a startup assertion or a health-check route that reports whether a Shibboleth session is visible.

Extension points, in order of usefulness. Decorate or replace the user provider (role mapping, JIT provisioning), subscribe to the bundle's authentication success event if it is dispatched (audit logging, last-login timestamps), override the Twig extension to change login-URL generation, and replace the firewall listener entirely if you need custom redirect behaviour (e.g. per-tenant IdP selection via entityID).

Plan the exit. Given the release age, put the Shibboleth integration behind a thin interface (IdentityProvider / SsoAuthenticator) in your own code so the bundle is a swappable dependency. When you migrate off Symfony 2, you replace one class instead of untangling firewall config from the rest of the app.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
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