sllh/hybridauth-bundle
Symfony bundle integrating HybridAuth social authentication, enabling login through providers like Facebook, Google, Twitter, and more with simple configuration and Symfony service integration.
Reality check before you composer require: this is a Symfony bundle, not a Laravel package. It depends on symfony/framework-bundle, symfony/security, and hybridauth/hybridauth ~2.x. It ships a Bundle class, a DI extension, and services.yml definitions intended for a Symfony kernel. On Laravel it will not boot; it just drags in a pile of Symfony components. Treat it as a reference implementation to crib from, not a day-to-day dependency — and definitely not for production auth (25 stars, zero dependents, HybridAuth 2.x is EOL/archived).
Where to look first, in order:
DependencyInjection/Configuration.php — the exact provider config shape (client_id, client_secret, scope, callback). It maps almost 1:1 to a HybridAuth constructor array, so it's your fastest crib sheet regardless of stack.Controller/ + Resources/config/routing.xml — the two-state endpoint (start + callback) and how the session round-trip is handled.Security/ — the hybrid_auth firewall provider/listener. Read it to understand why a dedicated guard is usually more machinery than you need.SLLHHybridAuthBundle.php + DependencyInjection/SLLHHybridAuthExtension.php — what services actually get registered and under what IDs.First use case: "Log in with Google/GitHub." Two routes, one controller, one social_accounts table. That's essentially the entire surface this bundle offers — it hands you a profile array and tokens, nothing more.
Laravel equivalent (what you'll actually build):
Route::get('/auth/{provider}', [SocialAuthController::class, 'redirect']);
Route::get('/auth/{provider}/callback', [SocialAuthController::class, 'callback']);
On Symfony, if you're inheriting a legacy app, enable the bundle, configure providers under the sllh_hybrid_auth key, wire the firewall provider, and then immediately plan the exit (see below).
Port the endpoint, not the bundle. The bundle's core pattern is a single URL with two states. In Laravel, redirect stashes the provider and intended redirect target in session, calls $hybridauth->authenticate($provider); callback calls isConnected(), getUserProfile(), links the account, and Auth::login(). That's ~40 lines of controller regardless of framework.
Account-linking table. The bundle stops at "here's a profile array" — persistence is yours in every stack. Use:
social_accounts (id, user_id, provider, provider_uid, token_json, expires_at)
-- UNIQUE (provider, provider_uid)
Resolution order: existing link → log in that user; no link but email matches a local account → prompt to link (never auto-link silently); no match → create user, then link. This one flow prevents most account-takeover edge cases.
On legacy Symfony, put an anti-corruption layer between your code and the bundle. Define your own SocialAuthProvider interface (redirect(), handleCallback(): SocialUser, refreshToken()), implement it today with the bundle, and reimplement behind it tomorrow with knpuniversity/oauth2-client-bundle / league/oauth2-client or HWIOAuthBundle. Controllers and user provisioning depend on your interface, never on HybridAuth classes — then the migration is a swap, not a rewrite.
Session round-trip is the fragile part. HybridAuth 2 assumes a shared session between start and callback. In a multi-instance load-balanced deployment, externalize sessions (Redis/DB) before you even think about horizontal scaling, or login will fail unpredictably against whichever node handles the callback.
Token storage: store access_token/refresh_token as a JSON blob plus a expires_at timestamp; refresh on read when expired rather than on a cron — the bundle gives you no refresh orchestration.
client_secret produces exactly the same symptom as a bad callback — add a health check that exercises each provider's authorize URL and alert on non-2xx/non-redirect.attacker controls provider A account with victim's email). Require an authenticated local session to link, or send a verification step.hybridauth.error_handler) before touching anything else — 80% of failures are provider-side rejection reasons (scope denial, redirect_uri mismatch, expired token exchange) surfaced only there.Bottom line for a developer: feature (social login) = yes; this package = no for new work. On Laravel use Socialite. On modern Symfony use league/oauth2-client or a managed IdP. If it's already in your tree, isolate it behind an interface, add contract tests per provider, and schedule removal on the next auth sprint.
How can I help you explore Laravel packages today?