Reader Stacks

Social Login in Laravel With Socialite (Google and Facebook)

Laravel Socialite handles the OAuth handshake for Google, Facebook, and several other providers behind one consistent API — the redirect, the callback, and mapping the returned profile onto a local user.

"Log in with Google" or "Log in with Facebook" both follow the same OAuth 2.0 pattern under the hood — Laravel Socialite is the official first-party package that implements that handshake for several major providers behind one consistent API, so the same basic code structure works whether the provider is Google, Facebook, GitHub, or others.

1. Installation and provider setup

composer require laravel/socialite
// config/services.php
'google' => [
    'client_id' => env('GOOGLE_CLIENT_ID'),
    'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    'redirect' => env('GOOGLE_REDIRECT_URI'),
],
'facebook' => [
    'client_id' => env('FACEBOOK_CLIENT_ID'),
    'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
    'redirect' => env('FACEBOOK_REDIRECT_URI'),
],

The client ID, secret, and redirect URI come from each provider's own developer console (Google Cloud Console, Facebook for Developers) — registering the app there and getting these three values is a prerequisite that happens outside of Laravel entirely, before any of the code below will work.

2. The redirect route

use Laravel\Socialite\Facades\Socialite;

Route::get('/auth/{provider}/redirect', function (string $provider) {
    return Socialite::driver($provider)->redirect();
});

This sends the user to the provider's own login/consent screen — Laravel doesn't render any login UI itself for this step; the entire authentication interaction happens on Google's or Facebook's own page.

3. The callback route

Route::get('/auth/{provider}/callback', function (string $provider) {
    $socialUser = Socialite::driver($provider)->user();

    $user = \App\Models\User::updateOrCreate(
        ['email' => $socialUser->getEmail()],
        [
            'name' => $socialUser->getName(),
            'google_id' => $provider === 'google' ? $socialUser->getId() : null,
            'avatar' => $socialUser->getAvatar(),
        ]
    );

    auth()->login($user);

    return redirect('/dashboard');
});

After the user approves access on the provider's page, they're redirected back to this callback URL with an authorization code Socialite exchanges for the actual profile data — $socialUser exposes getId(), getName(), getEmail(), and getAvatar() consistently across every supported provider.

4. Matching against an existing account by email

updateOrCreate() keyed on email is the standard pattern — it means a user who originally signed up with a password, and later clicks "Log in with Google" using the same email address, gets logged into their existing account rather than accidentally creating a duplicate one. This assumes the email from the provider is trusted and verified, which is generally true for Google and Facebook.

5. Stateless mode, for an API without sessions

Socialite::driver('google')->stateless()->user();

Socialite normally relies on session state to protect against CSRF during the OAuth flow — a stateless SPA or mobile-API backend that doesn't maintain a traditional session needs ->stateless() on both the redirect and callback calls, or the callback fails with a state-mismatch error.

6. The redirect URI must match exactly

The redirect URI registered in the provider's developer console must match the app's callback URL character-for-character, including the scheme (http vs https) and trailing slash — a mismatch here is the single most common setup error, and produces an error from the provider's own consent screen before the request even reaches Laravel's callback route.

Topics: Authentication & Access Control