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

Oauth Bundle Laravel Package

etcpasswd/oauth-bundle

A Symfony bundle that adds OAuth2 authentication to your security firewall, supporting providers like GitHub and Facebook, with multiple providers configurable at once. You still supply your own user provider.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony2 bundle, not a Composer package you can composer require into Laravel. It predates PSR-4 autoloading, ships no composer.json, and is installed by git clone into vendor/bundles. Treat it as a reference implementation of an OAuth2 firewall, not a dependency you will ever use inside app/.

First things to look at, in order:

  1. Resources/config/security_factories.xml — this is the whole integration surface. It registers the oauth firewall factory. Everything else (the listener, the token exchange) hangs off what that factory builds.
  2. The factory class it points to — this is where client_id, client_secret, scope, uid, login_path, check_path, failure_path are read and turned into a listener.
  3. The listener itself — it is the piece that replaces controllers. The README is explicit: "you do not need to build any controllers for either the login_path or the check_path." The listener intercepts the request, redirects to the provider, and handles the callback on check_path. Understand that control flow before anything else.
  4. The Buzz dependency (vendor/buzz). There is no HTTP client abstraction — Buzz is hard-wired in this era of Symfony. In Laravel this is the first thing you replace with Illuminate\Support\Facades\Http or Guzzle.

Your first use case should not be "install this". It should be:

"I have a Laravel app that needs an OAuth2 login against an API provider, and I want the Symfony firewall semantics (intercept login_path → redirect → handle check_path → fetch profile → authenticate) without writing it from scratch."

If that sounds like your situation, the honest first step is to open composer.json and see whether Laravel Socialite already has a driver for your provider. It usually does. This bundle is worth reading only when Socialite's assumptions don't fit — e.g. you need a firewall-style guard rather than a redirect-based controller flow, or you're porting a legacy Symfony2 app to Laravel and must preserve identity semantics (uid: email).

If you are genuinely porting, the minimal Laravel skeleton is:

// config/services.php
'myprovider' => [
    'client_id'     => env('OAUTH_CLIENT_ID'),
    'client_secret' => env('OAUTH_CLIENT_SECRET'),
    'redirect'      => env('OAUTH_REDIRECT_URI'),
    'scope'         => env('OAUTH_SCOPE', ''),
],
// routes/web.php
Route::get('/login',  [OAuthController::class, 'redirect'])->name('login');
Route::get('/auth',   [OAuthController::class, 'callback']);

That is the direct translation of login_path and check_path, and it is where you should start regardless of whether you read another line of this bundle.

Implementation Patterns

The Symfony pattern this bundle implements, restated for a Laravel dev. A firewall factory is a service that builds a listener from config. In Laravel the equivalent seam is a custom guard plus a Socialite driver, registered from a service provider. Keep those three concerns separate — the bundle conflates them into one config block, and that coupling is the main thing you should not copy.

Pattern 1 — Socialite driver as the port target (recommended).

// app/OAuth/MyProviderProvider.php extends AbstractProvider
public function getAuthUrl($state) { /* build authorize URL with client_id + scope */ }
public function getTokenUrl() { /* token endpoint */ }
protected function getUserByToken($token) { /* profile call using uid field */ }
protected function mapUserToObject(array $user) {
    return (new User)->setRaw($user)->map([
        'id'    => $user[$this->uid],   // bundle's `uid: email` maps here
        'email' => $user[$this->uid],
    ]);
}

Register it in a provider's boot() with Socialite::extend('myprovider', ...). This gives you the bundle's authorization-code flow with Laravel's HTTP client, state handling, and testability.

Pattern 2 — Controller flow, matching the firewall's interception. The bundle's listener means login_path never renders and check_path never needs a route body. In Laravel you do need both routes, but keep them dumb:

public function redirect() {
    return Socialite::driver('myprovider')
        ->scopes(config('services.myprovider.scope'))
        ->redirect();
}

public function callback(Request $request) {
    $remote = Socialite::driver('myprovider')->user();
    $user   = User::updateOrCreate(
        ['email' => $remote->getEmail()],
        ['name'  => $remote->getName(), 'provider_id' => $remote->getId()]
    );
    Auth::login($user, remember: true);
    return redirect()->intended('/');
}

Pattern 3 — Custom guard for stateless/hybrid use. If your API must accept a provider token directly (the bundle's firewall supports a check_path callback but you may want bearer-pass-through), implement Illuminate\Contracts\Auth\Guard and resolve it from Auth::extend(). This is the closest analogue to the auth_provider config key — the bundle expects a service id; you expect a guard driver name.

Pattern 4 — Porting the listener faithfully. If you must preserve behaviour for a migrated app, mirror the config keys one-to-one in config/oauth.php (auth_provider, client_id, client_secret, uid, scope, login_path, check_path, failure_path) and keep failure_path as a named route so redirect semantics on error match the old Symfony install. Then add one test per key. This is the cheapest way to prove the port is behaviourally equivalent.

Integration tips.

  • Wire the guard/driver in a dedicated service provider (OAuthServiceProvider), not AppServiceProvider. It keeps the Socialite::extend call and the guard registration in one auditable place, which is the Laravel analogue of security_factories.xml.
  • Map uid to a stable identifier. The bundle defaults users to email; emails change. Store provider_id alongside and key on that, falling back to email only for first-link.
  • Keep the provider's profile call in the driver, not the controller, so Http::fake() in tests covers it.
  • On failure, redirect to the configured failure_path with a flash message; never let the callback throw a 500 on ?error=access_denied.

Gotchas and Tips

  • It will not install in a modern Laravel app, and you should not try. No composer.json, no PSR-4, no type: symfony-bundle, no tests, zero dependents, README-only maturity. Cloning into vendor/ alongside a Composer-managed tree is a good way to have composer install delete your work. Read it, port the ideas.
  • The factories: key under security: is a Symfony 2.0/2.1-era convention that was replaced by SecurityExtension bundle registration. Even inside Symfony this config snippet is ancient. Don't take the YAML as current guidance — it is a historical artifact.
  • The listener handles login_path and check_path; there are no controllers to copy. The single biggest trap when porting is assuming you can lift controller code out. There isn't any. You are reconstructing an event listener as a route pair, and the control flow will not be line-for-line comparable.
  • auth_provider is a Symfony container service id, not a value. New developers paste auth_provider: api provider literally and get a container error. In Laravel this becomes a guard driver name resolved by Auth::extend() — make it a config constant, not a string in YAML.
  • Buzz is abandoned and unabstracted. Any port that keeps Buzz will be untestable without network access. Replace with the Laravel HTTP client on day one; it is the highest-leverage change you can make.
  • check_path: /auth is a POST/GET target the firewall matches against the request path. Under Laravel routing, mind trailing slashes and behind-proxy X-Forwarded-* headers — the original firewall compared the request path, and a misconfigured proxy can make the callback appear to arrive at a different path than the provider was told to redirect to. Set TrustProxies properly and keep the redirect URI in services.php identical to the one registered with the provider.
  • uid is your identity contract. The bundle's default (email) leaks through into user records if you port naively. Decide the merge strategy before writing updateOrCreate, and be explicit about what happens when two accounts arrive with the same email but different provider ids.
  • scope is a single string in the config; providers disagree on the delimiter. Some want space-delimited, some comma, some repeated query params. Put the formatting in the driver's getAuthUrl, not in config, or you'll be editing env vars per provider.
  • failure_path is a path, not a route name, in the bundle. Translating failure_path: / into redirect()->route('home') is right for Laravel, but if you are matching legacy behaviour, confirm whether the old app used a Location header with a relative path — tests that assert on assertRedirect('/') will catch the difference.
  • Extension point worth stealing: the firewall factory reads all provider-specific values from config and constructs the listener with no subclassing. That config-driven factory is genuinely a good idea for Laravel — expose a config/oauth.php array of providers and build drivers/guards from it, rather than hard-coding one driver per service provider method.
  • No tests means no contract. Nothing in this bundle tells you what failure_path does on network timeout vs. invalid client_secret vs. access_denied. When porting, write those three tests yourself; they are the ones that always regress.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log