sumocoders/oauth-bundle
A Symfony bundle from SumoCoders that adds OAuth authentication support, helping you integrate OAuth providers and secure your application with minimal configuration.
Reality check first: this is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config file in config/. If you are in a Laravel codebase, the practical path is to treat this repo as a reference implementation and use laravel/socialite instead — the bundle is essentially a thin Symfony Security wrapper around league/oauth2-client, and Socialite covers the same ground with a fraction of the wiring. Read the rest of this as "how to evaluate/port/borrow from it," plus how you'd use it if you actually are in a Symfony app.
What changed in v1.3.2: one commit, doctrine-bundle upgraded to 3.0. No new providers, no new config keys, no deprecations, no changes to the firewall listener or user-provider contract. It is a dependency bump, not a feature release — but it is a signal: DoctrineBundle 3.0 requires Symfony 6.4+/PHP 8.1+, so the maintainer's CI has almost certainly moved off the Symfony 4/5 era. Open composer.json and check whether doctrine-bundle landed in require or require-dev before assuming your Symfony version story.
Minimal steps in a Symfony app:
composer require sumocoders/oauth-bundle — read composer.json first, and read it carefully. If doctrine-bundle: ^3.0 is under require (not require-dev), Composer will force DoctrineBundle 3.0 into your app, which drags Symfony 6.4+/PHP 8.1 as a floor and conflicts with any app still on DoctrineBundle 2.x. If it is require-dev, it only reflects the package's own test matrix and you can ignore it. This distinction is now the single most important line in the file.SumoCoders\OAuthBundle\SumoCodersOAuthBundle in config/bundles.php (or AppKernel::registerBundles() on legacy).sumocoders_oauth: block with your client_id, client_secret, scopes, and redirect_uri for each provider (Google, GitHub, etc.).Where to look first, in this order:
composer.json — now doubly important. It pins both the league/oauth1-client / league/oauth2-client major version (which determines provider class names and method signatures) and, as of v1.3.2, the DoctrineBundle major. Check require vs require-dev.DependencyInjection/Configuration.php — the authoritative list of config keys. README examples drift; this file does not, and it is unchanged in v1.3.2, so any config you had working on v1.3.1 still works.Resources/config/services.* — service IDs, which you'll need for debug:container and for decoration.Security/Http/ — the firewall listener (the actual redirect/callback dance) and the authentication provider. Untouched by this release.Security/Core/User/ — the user provider interface you'll implement to bridge OAuth data into your own User entity.First use case: replace a hand-rolled "Login with Google" controller. You get the redirect/state handling and a Security token for free, at the cost of coupling your user model to the bundle's user provider contract.
Custom user provider (the one thing you'll definitely write). The bundle hands you the provider's response (access token + getResourceOwner() data); you decide what a local user looks like. Implement the bundle's user-provider interface and do just-in-time provisioning there:
(provider, provider_user_id), not by email.Symfony\Component\Security\Core\User\UserInterface; the bundle's own OAuthUser is fine for a prototype, replace it for real apps.Provider-per-firewall. The cleanest Symfony wiring is one firewall per provider (/auth/google, /auth/github), each with its own listener and user provider. This keeps scopes and redirect URIs unambiguous. A single firewall that switches on a query parameter works but you'll be fighting the security matcher.
Stateless/API variant. If you're using this to mint a token rather than start a session, use a stateless firewall with the OAuth listener and issue your own JWT/session-token in a success handler. Do not rely on the bundle's session token for a SPA — the redirect flow will fight your CSRF setup.
Porting to Laravel (if that's actually the job). The useful extraction is not the bundle, it's the sequence:
league/oauth2-client (new Google(['clientId' => ..., 'clientSecret' => ..., 'redirectUri' => ...])).getAuthorizationUrl(['state' => $state]), stash state in the session.state, handle ?error=access_denied before anything else, then getAccessToken('authorization_code', ['code' => $code]).$provider->getResourceOwner($token) and map to your user model — same (provider, provider_id) keying as above.That's ~60 lines in a Laravel controller and removes the Symfony coupling entirely. Note the DoctrineBundle bump changes nothing about this port — the league/oauth2-client surface is what you're copying, and it moved.
Testing. Never hit the real provider in tests. Swap the underlying league provider for a stub via container decoration (Symfony) or a bound fake (Laravel), and assert on state mismatch, error= callbacks, and the "existing user" vs "new user" branches of your user provider. Those three cases are where OAuth logins actually break. If you maintain a fork, the v1.3.2 DoctrineBundle bump is a reminder that your CI matrix is now effectively PHP 8.1+/Symfony 6.4+ whether or not you intended that — pin your own dev deps explicitly so a patch release doesn't silently move your test floor.
doctrine-bundle: ^3.0 is in require, Composer resolution will fail on apps pinned to DoctrineBundle 2.x / Symfony <6.4, and you'll get an opaque conflict message that looks like the OAuth bundle is incompatible when it's really the ORM layer. If it's in require-dev, nothing in your runtime changes and this release is a no-op for you. Don't skip that check before composer update.Configuration.php, the firewall listener, or the user-provider contract moved between v1.3.1 and v1.3.2. If you had a working integration, this is a safe patch upgrade barring the dependency conflict above. Equally: if you were waiting for a feature, this isn't it.Configuration.php and Resources/config/services.* over both the README and any inference from the changelog.www. all count. The single most common "invalid_grant" cause. Register both http://localhost and the ported variant during dev.state requires a session. If your app is API-only, has a custom session handler, or your callback is behind a load balancer without sticky sessions, the state check fails intermittently. Verify session persistence on the callback path before blaming the bundle.email_verified: false for some workspace accounts, GitHub email can be private/nulled, and users change emails. Key on the provider's immutable subject ID.?error= explicitly. Users hit "Cancel" on the consent screen constantly; the callback arrives with error=access_denied and no code. Unhandled, this is a 500 in your logs and a blank page for the user.access_type=offline for Google) to get a refresh token at all. The bundle does not refresh tokens for you — if the access token expires mid-session, you own that.anonymous: true is implicit but the matcher rules still bite; use bin/console debug:firewall <name> to confirm the listener is actually registered.bin/console debug:config sumocoders_oauth tells you what the current Configuration.php actually accepted — trust that over the README.dump()) inside the firewall listener's attemptAuthentication/onAuthenticationSuccess. Nine out of ten failures are visible in the exact URL and query params at that point.How can I help you explore Laravel packages today?