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

Openid Connect Bundle Laravel Package

itk-dev/openid-connect-bundle

Symfony bundle for OpenID Connect authentication. Configure OIDC providers, handle login and logout, discover endpoints, validate tokens, and map claims to users for secure single sign-on in Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small, single-vendor Symfony bundle from ITK Dev (Aarhus) that wires an OpenID Connect provider into Symfony's security layer. There is no Flex recipe, so treat it as a manual install.

  1. composer require itk-dev/openid-connect-bundle:^6.1 — pin it; there is one maintainer and no dependents to absorb churn for you.
  2. Register it in config/bundles.php and confirm the config root by opening DependencyInjection/Configuration.php — that file, not the README, is the authoritative list of options.
  3. Create config/packages/itk_dev_openid_connect.yaml with at least: issuer/discovery URL, client ID, client secret, redirect URI, and scopes (openid plus whatever claims you need — usually profile email). As of 6.1.0 scopes are explicitly configurable and the tree is bounds-checked, so a typo or a bad URI shape now fails at container build rather than at first login. That is the fastest feedback loop you will get — use it.
  4. Add a firewall with a dedicated provider and the bundle's authenticator, and set entry_point to it so unauthenticated hits get redirected to the IdP rather than a 401.
  5. First use case: protect one route (^/admin) end-to-end before touching anything else — log in, dump the received claims, hit the IdP's cancel button to exercise the new error-callback path, log out. Everything else (claim mapping, provisioning, multi-provider) is built on that loop.

Where to look first, in order: README.md and the two doc pages added in 6.1.0 (worker-mode contract, developing against a mock IdP), DependencyInjection/Configuration.php (read fully — it now encodes real validation), the authenticator/user-provider classes under Security/, then tests/. If the bundle wraps the sibling itk-dev/openid-connect library, read that package's README too — token, PKCE and discovery behaviour lives there.

Implementation Patterns

Single provider, JIT user provisioning. Let the bundle create local users from claims on first login, keyed on sub (never on email — emails change). Map only what you need into your User entity:

# config/packages/security.yaml (sketch)
firewalls:
    main:
        provider: oidc_users
        custom_authenticators: [ItkDev\OpenIdConnectBundle\Security\...Authenticator]
        entry_point: ItkDev\OpenIdConnectBundle\Security\...Authenticator

PKCE is now part of the flow. 6.1.0 sends a code challenge and keeps the verifier in session state rather than in a long-lived provider service. In practice this means the login round-trip is bound to the session — don't disable sessions on the firewall, and don't strip cookies on the callback route. If you have a confidential client against an IdP that rejects code_challenge for client_secret clients, that is a config question, not a code one; check the tree before patching.

Handle the error callback explicitly. The IdP can send ?error=access_denied (user hit cancel, consent refused, or the IdP is misconfigured) on the same redirect URI. Before 6.1.0 that surfaced as a stack trace; now the bundle routes it. Decide where it lands — logged, flashed, redirected to a friendly page — and assert it in a test. This is the most common user-visible bug in OIDC apps and it is now cheap to get right.

Two audiences, two firewalls. The common real-world shape is employees via one IdP and citizens/customers via another. Use separate firewalls (^/admin vs ^/), separate providers, and separate config entries. Keep the citizen firewall after the admin one so path matching resolves correctly.

Claims mapping as configuration, not code. Put the claim→property map in YAML and keep the mapping table in one place. When a claim is missing, default rather than throwing — IdPs silently drop scopes (e.g. email absent until the user consents). Now that scopes are explicit config, missing claims and missing scopes are the same debugging session: read the scope list first.

Refresh the local user per request. Don't trust a snapshot taken at login. Re-read roles/entitlements from claims (or a group claim) on each request, or you'll be manually clearing sessions after every role change.

Long-running workers. 6.1.0 publishes a worker-mode contract and gates it in CI (Igor) — so the state-leak class of bug is now something the maintainer tests for. If you run RoadRunner, Swoole, FrankenPHP worker mode or Octane-style workers, read that doc page before deploying: any per-request OIDC state (verifier, nonce, discovered provider) must live in session, not on a shared service. This is also the thing to re-check on every future upgrade.

Logout. Local logout: alone leaves the IdP session alive — the user bounces straight back in. Implement RP-initiated logout with id_token_hint and post_logout_redirect_uri, and register that URI at the IdP.

Local development. Don't add a dev-only bypass — that is exactly what ships to production. The 6.1.0 docs now describe developing against a mock identity provider; Keycloak in Docker is the path of least resistance and matches the documented shape.

Tests. Functional-test the firewall by mocking the authenticator or injecting a pre-built token; don't spin up a real IdP in CI. Assert the unauthenticated redirect, the error-callback redirect, and the post-login session, not the token internals.

Gotchas and Tips

  • Single maintainer, low bus factor. Still two stars and no known dependents, so pin an exact version and be ready to fork. The good news: 6.1.0 is six substantive PRs from the maintainer with CI gates added, so this is maintained software, not abandoned software. Budget hours for reading, not a day — the docs are meaningfully better than they were.
  • The 6.1.0 upgrade is small but not free. No deprecations or breaking changes are announced, but two things change behaviour: PKCE is now sent on every authorization request, and providers are no longer held between requests. Test the full login/logout round-trip on staging before rolling out, and specifically test any IdP that was configured against a 6.0.x flow.
  • Redirect URI must match byte-for-byte. Scheme, host, port, trailing slash. The single most common failure is a mismatch that surfaces as a generic IdP error page — or now, as an error callback on a route you haven't styled.
  • Behind a proxy, everything breaks quietly. Set trusted_proxies and X-Forwarded-Proto, or Symfony generates http:// redirect URIs and the IdP rejects them.
  • Discovery fetching at boot. If the bundle resolves the well-known document eagerly, a container build or cache warmup without network access will fail. Check whether the discovery document is cached and where. Tighter config bounds in 6.1.0 make boot failures earlier and loud — read the exception message rather than guessing.
  • Scopes are opt-in and now explicit. No openid scope, no ID token. Missing profile/email, missing claims — and the bundle may not warn, it just gives you a user with nulls. The new config bounds catch structurally invalid values, not semantically insufficient ones.
  • Use sub as the identifier. Any IdP migration that changes issuer will break sub stability too; store (issuer, sub) if you ever expect a second IdP.
  • Clock skew. Token nbf/exp validation on a VM with drifting time produces intermittent login failures that look random. Run NTP.
  • Debugging loop: -vvv on the console, then the Symfony profiler's security panel, then decode the ID token payload to see what actually arrived. If the redirect never reaches your firewall, it's an IdP-side config problem — stop looking in Symfony. If it reaches you and bounces back, it's PKCE/session/redirect-URI, in that order.
  • Extension points: decorate the user provider or subscribe to the security events rather than editing vendor code; add a custom claim mapper if the built-in mapping is too rigid. Both survive composer update; patches don't.
  • Watch the worker-mode CI gate. If Igor starts flagging things after an upgrade, it means the bundle's contract tightened — read the doc page before dismissing the failure.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
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