jostkleigrewe/lib-php-eurip-sso
A PHP library for integrating EURIP single sign-on (SSO) into your applications, with helpers for authentication flows and session handling to simplify adding SSO support to Laravel or plain PHP projects.
Architecture fit. Despite being filed as a "Laravel/PHP package," the artifacts here are unambiguously a Symfony bundle (config/services.yaml resource scanning, #[AsEventListener], #[Autowire], #[Route], Twig functions, bundle extension, symfony/ux-twig-component). There is no Laravel service provider, facade contract, or Eloquent/session integration in evidence. A Laravel consumer would need a bespoke adapter and would inherit Symfony HTTP kernel assumptions — treat this as "not a fit" unless the target app is Symfony 7/8. Flag this mismatch to whoever scoped the intake before anything else moves.
Assuming a Symfony target, the architecture is now more idiomatic than prior iterations: controllers are thin, business logic moved to OidcAuthenticationService, JWT signature verification is extracted into a framework-agnostic JwtVerifier (PSR-18/17/3), and DI is driven by resource scanning rather than manual wiring. That is a genuine quality improvement, and it makes the package easier to reason about and to test in isolation.
Integration feasibility. Feasible but expensive. v0.3.0 is a hard break with no deprecation shim:
OidcClient::__construct() gains JwtVerifier as the 5th positional parameter, before the optional logger — any call site passing a logger positionally now fails at runtime with a TypeError that is easy to misread.OidcConstants changed from interface to final class — every implements OidcConstants becomes a fatal error.::NAME event constants and OidcConstants::EVENT_* are gone; listeners must be rewritten to class-based dispatch.OidcController, and OidcRouteLoader are removed; fromDiscovery() and all four JWKS methods on OidcClient are gone.controller.enabled, client_services.enabled, client_services.store_access_token, and three authenticator.* keys are removed — these fail at container compile, not subtly, which is actually a mercy.Counterweights: route names are explicitly unchanged (huge for bookmarks, IdP redirect URIs, and tests), the event/controller/exception surface is better designed, and the new console commands (eurip:sso:cache-warmup, eurip:sso:test-connection, device-login, client-credentials, introspect) give us pre-deploy verification and new integration patterns we previously had to build ourselves.
Technical risk. Medium-high, concentrated in three areas:
OidcClient + 15 JwtVerifier)" is stated with pride, but it also reveals that controllers, OidcAuthenticationService, exceptions, commands, Twig functions, and the logout component have no tests in CI. For auth-critical code in a breaking release, that is the biggest quality question — and it matters more than PHPStan Level 6, which only proves types, not behavior.::NAME constants, a typo failed loudly. With type-hint-inferred listeners, a listener that doesn't fire produces no error. This is a real observability regression during migration.Key questions.
Stack fit. Requires PHP 8.4+, Symfony 7.0/8.0+, Twig for the template helpers, and optionally symfony/ux-twig-component for <twig:EuripSso:Logout />. The JwtVerifier is deliberately framework-agnostic (PSR-18/17/3) and can be reused standalone if we ever need JWT verification outside the bundle — a small but real reuse win. If we are a Laravel shop, stop here and re-scope.
Migration path. Treat the release notes as a literal checklist, in this order:
controller.enabled, client_services.*, authenticator.callback_route/default_target_path/login_path) and move anything custom to routes.*; let the compile step find stragglers.EuripSsoFacade injections with FQCN constructor injection; drop implements OidcConstants everywhere.#[AsEventListener] with the event type on __invoke(); delete constant references. Add a temporary log line in each listener and confirm each fires in staging before removing it.JwtVerifier via OidcClientFactory::create(), or if constructing directly, insert it as the 5th argument and audit any positional logger usage.preloadJwks(), fetchAndCacheJwks(), hasJwksLoaded(), invalidateJwksCache() and fromDiscovery() to OidcClientFactory / JwtVerifier.OidcController, port to AuthenticationController / ProfileController / DiagnosticsController; confirm eurip_sso_login, eurip_sso_callback, eurip_sso_logout still resolve and that the IdP's registered redirect URI is unchanged.Compatibility. Clean break, no shim. Two viable paths: (a) full upgrade now, budgeting for a real migration ticket rather than a dependency bump; (b) stay pinned to v0.2.x if the PHP 8.4 bump can't land this cycle — acceptable only if we accept missing the JwtVerifier hardening and key-rotation resilience.
Sequencing. Spike on a branch → run eurip:sso:test-connection and eurip:sso:cache-warmup against the staging IdP → exercise login, callback, logout, profile, debug, and both logout channels → verify event listeners fire → cut over. Keep v0.2.x deployable for one release cycle as rollback. Do not pair this migration with unrelated framework upgrades.
Maintenance. Pre-1.0 with a demonstrated willingness to remove classes, aliases, constants, and config keys without a deprecation window. Expect a repeat of this cost at 0.4/0.5. Auto-registration via resource scanning reduces bespoke wiring we must maintain, but it also removes control: with controller.enabled and client_services.enabled gone, we can no longer selectively disable controllers or service registration per environment — only authenticator.enabled remains. If we relied on those toggles to keep debug/test endpoints out of production, that must now be handled at the routing/proxy layer. Attribute-based routes also mean route changes are code changes; the dynamic loader's flexibility is gone (though defaults for profile, debug, test are sensible).
Support. Documentation is the strongest part of this release: Mermaid flow diagrams, session management guide, device-code and M2M guides, all in EN and DE. That materially lowers onboarding and support burden for a distributed/EU team. Against that: 60 tests covering only two classes means support tickets for controller/service/command behavior will be diagnosed by reading code, not by CI. PHPStan Level 6 and ECS PSR-12 are good hygiene signals but weak correctness signals for an auth library.
Scaling. Positive: JwtVerifier caches JWKS with TTL management, buildJwksCacheKey() is public, and eurip:sso:cache-warmup lets us prime discovery + JWKS at deploy time rather than on first user request — that removes a classic cold-start auth latency spike. Caveat: the cache must be shared across nodes, or every pod maintains its own JWKS copy and refreshes independently. Key-rotation handling (invalidate → refetch → verify) is correct but means a rotation event triggers a refetch from every node simultaneously; budget for that burst and consider staggering or a shared cache with a lock. Session management polling adds steady IdP load proportional to interval — choose it deliberately, don't leave it default. Back-/front-channel logout endpoints introduce inbound traffic paths that need to be reachable and rate-tolerant.
Failure modes.
implements OidcConstants fail at container compile — loud, safe, fast to fix.JwtVerifier inserted before the logger causes TypeError in any positional construction — audible in tests, but only if those call sites are exercised.symfony/ux-twig-component; without it, template rendering breaks at request time, not boot time.OidcAuthenticationException with the OidcErrorCode enum (INVALID_STATE, MISSING_CODE, TOKEN_EXCHANGE_FAILED, INVALID_ID_TOKEN, CLAIMS_VALIDATION_FAILED, PROVIDER_ERROR) is a real improvement — but only if we map those codes into metrics and alerts rather than logging a generic string.Ramp-up. Low-to-moderate for Symfony developers. Class-based listeners, SelfValidatingPassport with UserBadge, and attribute routes are now standard Symfony idiom, so the migration mostly reduces bespoke knowledge. The new surface to learn is the operational tooling: device code flow (RFC 8628), client credentials + introspection (RFC 7662), OIDC Session Management, and cache warmup in the deploy pipeline. Most of that only needs one person to own it. Non-Symfony developers — and anyone who assumed this was a Laravel package — will need real ramp-up time, and the framework mismatch should be resolved before it consumes a sprint.
How can I help you explore Laravel packages today?