jumbojett/openid-connect-php
A lightweight PHP client for OpenID Connect. It supports authorization code flow, token exchange, userinfo retrieval, ID token validation via JWKS, and logout, making it easy to add secure OIDC login to PHP applications.
Architecture fit. jumbojett/openid-connect-php is a deliberately thin OpenID Connect Relying Party: one primary class (OpenIDConnectClient) that performs discovery, authorization-code redirect, code-for-token exchange, ID token signature validation against the IdP's JWKS, and a userinfo call. It owns no session, no routing, no config, no user model, and no persistence. That is the right shape for a Laravel codebase: it slots in as an implementation detail behind an adapter you own (App\Auth\Oidc\...), and your service provider, config, routes, middleware, claim mapper, and user-provisioning logic stay yours. It is a poor fit if you want it to be the identity layer — it has no multi-tenant IdP registry, no role mapping, no SCIM/provisioning, no logout orchestration, and no token lifecycle management.
Integration feasibility. Composer-installable, no Laravel coupling to unwind, so baseline integration is small: a config file, a service-provider binding, two routes, a controller pair, a claim→user mapper, and tests. Two friction points drive the real estimate:
state, nonce, and PKCE verifier in native PHP session storage by default. Under Laravel that collides with non-file session drivers, stateless/API contexts, and multi-node deployments. Expect to either force a shared session driver or inject Laravel's cache/session via subclass or a delegating wrapper — confirm the injection hooks exist in the version you pin (HTTP client abstraction has historically been curl-centric).Effort for a conventional web app with one IdP: 8–12 engineer-days end to end (spike 1–2, wrapper 1, claim mapping + existing-user migration 2–4, security review 1–2, tests 2, rollout 1), plus review.
Technical risk.
| Risk | Severity | Mitigation |
|---|---|---|
| Token/claim validation correctness — the library historically hand-rolled JWT/JWKS handling and has carried security advisories | High (this is the security value of the package) | Pin an exact version past all advisories, run composer audit in CI, add negative tests (wrong aud, wrong iss, expired, alg=none, tampered signature). For regulated scope, validate independently with firebase/php-jwt or web-token/jwt-framework |
| Low-velocity, effectively single-maintainer project (739 stars, low opportunity score, last release 2024-09) | Medium | Treat as vendored dependency: internal owner, advisory subscription, budgeted fork capability (single class makes a fork tractable) |
| Native-session assumption / state loss | Medium | Shared session store, explicit state TTL, runbook for "invalid state" |
| Missing enterprise features (RP-initiated and back-channel logout, refresh, PAR, DPoP) | Medium | Scope explicitly; these become your code or a different library |
| Sparse docs and thin community answers | Low–Medium | Buy down with an internal design doc and golden-path tests |
Key questions.
Stack fit. Laravel 10/11/12 on PHP 8.1+ (verify the pinned version's PHP constraint). Coexists cleanly with Socialite for consumer social logins and with Sanctum/Passport for API tokens — this library is the enterprise-SSO front door only. It does not conflict with existing middleware; the callback route sits on web for session access.
Migration path. Ship behind a flag and in parallel with existing auth:
composer require jumbojett/openid-connect-php:<pinned>, one IdP (Entra ID / Okta / Keycloak), happy path plus one tampered-token test. Kill or confirm in 2 days.config/oidc.php (issuer, client id/secret, redirect URI, scopes, claim mapping, clock skew), OidcServiceProvider binding a factory, cache-backed JWKS/discovery store.GET /auth/oidc/redirect and GET /auth/oidc/callback, named, rate-limited, with redirect_uri built from route() under forced HTTPS.oidc_identities(provider, issuer, subject, user_id, timestamps, unique) — key on iss+sub, never email. Just-in-time user creation off configurable claims; explicit linking flow for pre-existing password users (verify-then-link, never silent merge by email).Compatibility. Requires a shared session driver (Redis/DB, not file) if you rely on the library's state handling; behind load balancers, verify X-Forwarded-Proto/host handling so redirect_uri matches exactly at the IdP; set Secure/SameSite=Lax cookies; set explicit iat/exp clock-skew tolerance; confirm discovery and JWKS are cached rather than fetched per request.
Sequencing. Security review of the validation path should gate the shadow-mode exit, not the spike — you need working traffic before the review is meaningful. Keep the claim mapping behind an interface so that if you later swap to a PSR-18-native alternative (e.g. facile-it/php-openid-client) the blast radius is one class, because every call site goes through your adapter. That optionality is the main reason to accept the maintenance burden of a wrapper for a 700-star single-class library.
Maintenance. You own a thin auth wrapper: budget roughly 1 engineer-week per quarter for dependency bumps, advisory triage, IdP metadata/certificate rotations, and test upkeep. Standing controls: pinned version, composer audit and composer outdated in CI, Dependabot/Renovate on the package, and a documented fork procedure (single-class, Apache-2.0 — forkable in hours, which materially de-risks the low-maintainer-velocity profile).
Support. No vendor support; community and upstream issues only. Define a named internal owner and a tier-1 escalation path: authentication failure is a full login outage for SSO users, so it belongs in the top tier alongside the database. Have a documented break-glass path (password login or admin-issued magic link) that does not depend on the IdP.
Scaling. The RP flow itself is negligible load. The cost centres are outbound HTTP: discovery and JWKS fetches (cache with ~1h TTL plus background refresh — uncached fetches add latency on every login and can trip IdP rate limits, especially under a login stampede), and the token endpoint round trip (commonly 100–500 ms). Reuse a configured HTTP client with connect/read timeouts and bounded retries; never hold a DB transaction across the token exchange; keep the callback handler idempotent so retries are safe.
Failure modes and runbook.
| Symptom | Likely cause | Action |
|---|---|---|
| "Invalid state" / state not found | Session lost — wrong session driver, multi-node mismatch, cookie eviction, user idle past TTL | Check session driver consistency and state TTL; surface a friendly re-login |
| Signature verification failure | JWKS stale after IdP key rotation; cached discovery | Flush JWKS cache; confirm refresh path; alert on first occurrence |
redirect_uri mismatch |
Proxy/scheme/host drift or config change | Pin the URI in config and at the IdP; verify forwarded headers |
nonce mismatch / replay rejection |
Cached callback page or double-submit | Ensure callback is non-cacheable and single-use |
| Token endpoint 5xx / timeout | IdP incident or egress issue | Circuit-break to break-glass login; status-page watch |
aud/iss mismatch |
Wrong client id or multi-tenant issuer format | Validate config per environment in a health check |
| Intermittent auth failures only on some nodes | Session and cache not shared | Consolidate on Redis/DB |
Instrument the callback path with structured logs (issuer, outcome, latency, failure class — never tokens or PII) and an alert on callback error rate.
Ramp-up. An engineer who knows OAuth 2.0/OIDC needs about half a day with the wrapper plus an internal doc containing the sequence diagram, the claim contract, and the failure-mode table. Without that background, budget 2–3 days of reading plus a paired review — do not let the library's "minimalist" framing substitute for understanding the authorization-code + PKCE + ID-token-validation flow, because that knowledge is what the security review will test.
Recommendation. Adopt, wrapped, pinned, and cached — but scope it as a browser SSO relying party for a small number of known IdPs. Escalate to a PSR-18-native alternative if the roadmap requires multi-tenant arbitrary issuers, back-channel logout, refresh-token management, or evidence-grade library provenance; the wrapper boundary keeps that switch to roughly 1–2 engineer-days.
How can I help you explore Laravel packages today?