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

Stepup Gssp Bundle Laravel Package

surfnet/stepup-gssp-bundle

A Symfony bundle for implementing a Generic SAML Step-up Provider (GSSP). It enables applications to request extra authentication, such as a second factor, via SAML, with configurable routes, controllers, and services for integrating Stepup flows into PHP/Symfony projects.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony 6 bundle, not a Laravel package — that distinction shapes everything below. You can read it as "a reference implementation of the GSSP (Generic SAML Step-up Provider) profile" and either (a) run it in a small Symfony sidecar app that handles only the step-up handshake, or (b) mine it for the flow and re-implement the ~3 services in Laravel. Trying to composer require it into a Laravel app will drag in symfony/http-kernel, symfony/dependency-injection, and the bundle registration contract, which Laravel does not satisfy.

Minimal steps if you are standing it up inside Symfony (the only supported path):

  1. composer require surfnet/stepup-gssp-bundle
  2. Register the bundle in config/bundles.php (Surfnet\StepupBundle\SurfnetStepupBundle::class => ['all' => true]).
  3. Publish/author the bundle config (look for surfnet_stepup.yaml in the bundle's DependencyInjection/Configuration.php) — you need at minimum your own entity ID, the remote IdP metadata, and the LoA levels you accept.
  4. Import the bundle's routing (@SurfnetStepupBundle/Resources/config/routing.yaml or the attribute-routed controllers) so the step-up endpoints exist.
  5. Your IdP needs to know about this SP and about the AuthnContextClassRef values you will request — the GSSP profile is fundamentally about asking an IdP for a higher LoA than the one you already have.

First use case to target: a single route that requires LoA 2 while the user currently has LoA 1. Send them into the step-up endpoint, let the bundle build the AuthnRequest with the elevated AuthnContextClassRef, and on return resume whatever they were doing. Get that one round trip working before touching anything else.

First places to look in the repo: README.md, DependencyInjection/Configuration.php (the real API surface), the Controller/ directory (the actual endpoints you get), and Service/ (the pieces you would port to Laravel).

Implementation Patterns

The canonical step-up flow. The bundle exists to model this sequence, and every pattern below is a variation on it:

  1. Incoming request hits a route guarded at LoA 1.
  2. Application decides the resource needs LoA 2 and calls the step-up service with the target LoA plus a "return to" URL.
  3. The bundle persists the pending request in session and issues a SAML AuthnRequest with the higher AuthnContextClassRef.
  4. User authenticates at the IdP with the stronger factor.
  5. IdP posts back to the assertion consumer endpoint; the bundle validates and updates the session's LoA.
  6. Application resumes the original request.

If you are porting to Laravel, that maps cleanly onto: a StepUp service, a PendingRequest session key, a controller for the ACS endpoint, and a middleware that checks session('loa') >= route_requirement.

Guard-as-middleware. The Symfony equivalent of Laravel middleware is an event listener on kernel.request. Whatever you build, keep the LoA check in one place and have route requirements declared as metadata (attributes or config array) rather than inline if statements. The bundle's flow assumes the guard knows the required LoA and the current LoA; don't scatter that comparison.

Preserve the intended destination. The single most common production bug in step-up flows is losing the user's original URL. Store the intended path in the session before redirecting to the IdP, and restore it on the ACS return — never rely on the IdP to echo it back. Treat this as a first-class concept (PendingStepUp value object with returnTo, requiredLoa, createdAt), not as an ad-hoc session key.

Session continuity across the round trip. The state written before the redirect must be readable after the IdP posts back. In a multi-node deployment that means a shared session store (Redis/DB), not files. In a Laravel context this is your SESSION_DRIVER plus a stable SESSION_COOKIE domain — SameSite settings and the redirect dance are where this breaks.

Testing. The valuable thing to test is the decision logic, not the SAML wire format. Extract "does this request need step-up?" and "did the returned LoA satisfy the requirement?" into pure functions/services and unit-test those. For the ACS endpoint, test with fixture assertions (valid, expired, wrong audience, insufficient LoA) rather than mocking the whole XML-DSig stack.

Integration tip for the sidecar approach. If you run this bundle as a separate Symfony app, put it behind the same cookie domain as your Laravel app and have it redirect back with a signed, short-lived token containing the achieved LoA. Do not have the Symfony app write directly into Laravel's session — that coupling will bite you.

Gotchas and Tips

It is not a Laravel package, and pretending otherwise is the biggest pitfall. No service provider, no facades, no config/ publish tag. Budget for either a sidecar app or a manual port. Given the repo has 1 star and 0 dependents, treat it as a well-structured reference, not a dependency.

LoA values are IdP-negotiated, not app-chosen. You request a specific AuthnContextClassRef; the IdP decides what it will actually assert. If your config requests an LoA the IdP does not support, you will get a silent fallback or an error at the IdP, not a nice exception in your app. Verify the exact URNs against your IdP's metadata before writing any code, and log the AuthnContextClassRef actually returned.

Session state and SAML InResponseTo must line up. The bundle correlates the response with the outstanding request ID. If the session is regenerated (login, CSRF rotation, load balancer with sticky-session off), correlation fails and you get an unhelpful "no matching request" error. Check session stability first whenever the ACS endpoint misbehaves.

Configuration is the API. Nearly every behavioural knob lives in the bundle's Configuration.php. Read that file directly rather than the README — the README will lag the tree. Look for the LoA-to-AuthnContextClassRef mapping, the allowed-clock-skew / assertion-validity settings, and the route paths.

Clock skew. SAML assertions have NotBefore/NotOnOrAfter. Default tolerance is usually tight. In containers with drifting clocks you will see intermittent "assertion not yet valid" failures that look random. Ensure NTP and, if exposed, widen tolerance modestly.

Debugging. The failure modes are almost all "redirect happened, nothing useful in the logs." Enable the bundle's logger and log: (1) the outgoing AuthnRequest ID, (2) the required LoA, (3) the returned AuthnContextClassRef, (4) the pending-request lookup result. Those four lines will diagnose the large majority of issues.

Extension points. If you do adopt the bundle, the clean seams are the step-up service (override to change how the return URL is computed), the event dispatcher (hook the pre-redirect and post-ACS points to add audit logging), and the routing config (repoint endpoints under your own firewall). Avoid subclassing controllers — the flow is small enough that forking the logic is safer than overriding half of it.

Maintenance risk. Last release date is far in the future relative to typical project clocks and the project has effectively no downstream users. Pin the version, vendor the parts you rely on if you fork, and keep the SAML library (simplesamlphp/lightsaml, whichever it pins) independently patched — that is where the real security surface lives, not in this bundle.

License is fine. Apache-2.0 means porting the flow into Laravel is legally uncontroversial; keep the NOTICE/attribution if you copy source.

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.
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
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin