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

Filament Socialite Laravel Package

jeffersongoncalves/filament-socialite

A Filament plugin that adds social login to your admin panel using Laravel Socialite. Let users sign in with Google, GitHub, Facebook, and other providers, with easy configuration of providers, buttons, and redirects for a smooth authentication experience.

View on GitHub
Deep Wiki
Context7

Getting Started

This is the first Filament v4 release of the plugin (2.0.0), so there is no upgrade path to worry about — but it also means the API is young and the README is the primary reference.

Install and register

composer require jeffersongoncalves/filament-socialite

Add the plugin to the panel you want social login on (typically app/Providers/Filament/AdminPanelProvider.php):

use JeffersonGoncalves\FilamentSocialite\SocialitePlugin;
use JeffersonGoncalves\FilamentSocialite\Provider;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(
            SocialitePlugin::make()
                ->providers([
                    Provider::make('github')
                        ->label('GitHub')
                        ->icon('heroicon-o-code-bracket')
                        ->color('gray'),
                    Provider::make('google')
                        ->label('Google')
                        ->color('danger'),
                ])
        );
}

Configure the OAuth app

  1. Create the OAuth app with each provider (GitHub, Google, …) and paste the credentials into config/services.php / .env as you would for plain Laravel Socialite (GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, …).
  2. Get the callback URL the package registered for your panel — do not hand-write it. Use php artisan route:list | grep -i socialite (or route('filament.admin.auth.socialite.callback', ['provider' => 'github'])) and paste that exact absolute URL into the provider's dashboard.

First use case: "Sign in with GitHub" on the admin panel for a small team. Register one provider, point the OAuth app at the generated callback, hit /admin/login, click the button. That's the whole loop — no controller, no route file, no Blade view.

Where to look first when something is wrong

  • php artisan route:list --path=socialite — confirms routes exist on the right panel.
  • The panel's login page HTML — confirms the button rendered (hook AUTH_LOGIN_FORM_AFTER).
  • storage/logs/laravel.log — Socialite exceptions (invalid state, redirect mismatch) surface there.
  • The companion package jeffersongoncalves/laravel-socialite — that's where the social-account persistence and linking logic lives; read its README when you touch linked accounts.

Implementation Patterns

Multi-panel installations. Routes are registered inside each panel, so admin and app panels each get their own redirect/callback pair. This is a feature, not a nuisance: register the plugin only on the panels that should have it, and add one redirect URI per panel to the OAuth app (GitHub allows multiple; providers that allow only one force you to use separate OAuth apps per panel).

Gating who may use social login. Combine canAccessPanel() with a provider-level allowlist so a Google login can't walk into the admin panel:

->plugin(
    SocialitePlugin::make()
        ->providers([Provider::make('google')])
        ->canAccessPanel(fn (User $user) => $user->hasRole('staff'))
)

Treat this as the authorization boundary — the panel's own canAccessPanel() on the FilamentUser contract still applies, but failing fast here gives a cleaner error than a redirect loop.

Account creation policy. Three states, pick deliberately:

  • Registration disabled → only users that already exist (matched by email) can sign in. Safest for internal tools.
  • Registration enabled, default behaviour → a user row is created from the provider payload.
  • Registration enabled + createUserUsing() → you own the mapping. This is where you normalise names, assign a default role, set email_verified_at, generate a username, or attach a tenant:
->createUserUsing(function (string $provider, $socialUser) {
    return User::create([
        'name'              => $socialUser->getName() ?? $socialUser->getNickname(),
        'email'             => $socialUser->getEmail(),
        'email_verified_at' => now(),
        'password'          => Str::password(32), // never null-blocked by a NOT NULL column
    ])->assignRole('member');
})

Resolving existing users. resolveUserUsing() overrides the email lookup. Use it when your user table is keyed on something other than email, when you want to honour soft-deleted users, or when you want to refuse an automatic link until an admin approves:

->resolveUserUsing(fn (string $provider, $socialUser) =>
    User::where('email', $socialUser->getEmail())->whereNotNull('email_verified_at')->first()
)

Scopes and extra parameters. Push the minimum scopes you actually need (->scopes(['read:user', 'user:email'])); extra params cover provider-specific flags — Google's prompt=select_account, or access_type=offline when you intend to store refresh tokens. Keep stateless() out of browser flows (see Gotchas).

Customizing the button placement. Buttons are injected through AUTH_LOGIN_FORM_AFTER. Register your own render hook on the same or a different hook to add a divider ("or continue with"), reorder providers, or wrap the block in your own markup — the plugin exposes the hook name so you can target it explicitly rather than guessing.

Linked accounts for signed-in users. The companion laravel-socialite package supplies the social-account relation. Typical pattern: a Filament profile page with an Action per provider — "Connect GitHub" when unattached, "Disconnect" when attached — reusing the same redirect route but flagged as a linking flow so the callback attaches instead of logging in. Keep the disconnect action behind a confirmation and consider blocking it when it's the user's only login method.

Localization. English and pt_BR ship in-tree. Publish to override strings (vendor:publish --tag=…socialite…-translations, check the README for the exact tag) rather than forking, and set app()->setLocale() per panel if you run a bilingual admin.

Testing. Fake the handshake instead of hitting providers:

Socialite::fake('github', (new \Laravel\Socialite\Two\User)->map([
    'id' => '123', 'name' => 'Jane', 'email' => '[email protected]', 'nickname' => 'jane',
]));

$this->get(route('filament.admin.auth.socialite.callback', ['provider' => 'github']))
     ->assertRedirect('/admin');

Assert the negative cases too: unknown provider, disabled registration, canAccessPanel denial.

Gotchas and Tips

Redirect URI mismatch is the #1 failure. The package generates the callback URL from the current request's host and scheme. Behind a proxy, a load balancer, or in a container without TrustProxies configured, the generated URL can be http:// or an internal hostname — the OAuth app then rejects it. Fix TrustProxies / APP_URL / ASSET_URL before debugging the package, and verify the URL in route:list matches the provider dashboard character for character (including trailing slash and port).

stateless() is not a drop-in toggle. It disables state validation on the redirect. Fine for machine-to-machine or a deliberately locked-down single-provider flow; wrong for the normal browser login, where it re-opens CSRF-style callback forgery. Also, stateless flows generally can't do account linking, which needs the authenticated session context.

Session driver matters. The OAuth handshake stores state in the session. A token/array session driver, an API-only guard, or a SPA issuing requests without cookies will break the callback with a cryptic "invalid state". Keep the browser flow on the web middleware group with cookie sessions.

Email trust. Auto-linking by email is only as trustworthy as the provider's email claim. Providers that don't verify emails, or that return a null/unverified email, are a takeover vector if you link onto an existing local account blindly. Prefer a resolveUserUsing() that checks email_verified_at on the local side, or require an explicit confirmation step for links.

Guard against missing password columns. If users.password is NOT NULL and you enable registration with a custom createUserUsing(), you must supply a value (random hash) or the insert fails. Users created this way should also be marked as having no usable password so a "forgot password" flow doesn't surprise them — or, conversely, wire up a set-password prompt after first social sign-in.

Registration scope. registration being enabled is global to the plugin instance; with multiple panels, configure each panel's plugin separately rather than sharing one instance across panels.

Route and provider name consistency. The Provider::make('github') key must match the Socialite driver name registered in config/services.php (services.github). Typos here produce "Driver [github] is not supported" from deep inside Socialite, not from the plugin.

Version pinning. This is a 2.0.0 first release for Filament v4 — the fluent Provider API is likely to grow. Pin ^2.0 in composer.json, and re-read release notes before minor bumps; hook names and method signatures are the most probable breaking surface.

Upgrading from Filament v3 era tooling. Nothing in this release is deprecated — the v3 equivalents are simply not covered by this version. If you had a hand-rolled Socialite controller, delete its routes when adopting the plugin; two routes answering the same callback path produce confusing, order-dependent behaviour.

Debugging checklist when the button doesn't appear: confirm the plugin is on that panel, confirm providers() is non-empty, then check whether your own render-hook override replaced the AUTH_LOGIN_FORM_AFTER block. When the button appears but the redirect 500s, it's almost always missing client_id/client_secret or an unpublished migration for the social-accounts table from the companion package (php artisan migrate after vendor:publish).

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.
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
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator