Laravel Socialite abstracts OAuth-based social login behind one consistent interface — adding both Google and Facebook login is mostly a matter of repeating the same three-step pattern once per provider, with a different driver name and credential set each time.
Installing Socialite
composer require laravel/socialite
Configuring provider credentials
// 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 redirect route: sending the user to the provider
use Laravel\Socialite\Facades\Socialite;
Route::get('/auth/{provider}/redirect', function (string $provider) {
return Socialite::driver($provider)->redirect();
});
Parameterizing the driver name ({provider}) rather than hardcoding it lets a single route handle both Google and Facebook (or any other configured provider) — the string passed in the URL maps directly to Socialite::driver()'s expected value.
The callback route: handling the provider's response
Route::get('/auth/{provider}/callback', function (string $provider) {
$socialUser = Socialite::driver($provider)->user();
$user = User::updateOrCreate(
['email' => $socialUser->getEmail()],
[
'name' => $socialUser->getName(),
$provider.'_id' => $socialUser->getId(),
]
);
Auth::login($user);
return redirect('/dashboard');
});
updateOrCreate(), matched on email, handles both a genuinely new social sign-up and a returning user logging in again through the same provider — using email as the matching key also allows a user to later log in via a second provider and correctly link to their existing account, rather than creating a duplicate.
The login buttons
Login with Google
Login with Facebook
Registering both providers' callback URLs with each platform
Both Google Cloud Console and the Facebook Developer portal require the exact callback URL to be pre-registered in their respective app settings — a mismatch between the registered URL and the one Laravel actually redirects to (including the exact scheme, domain, and path) is one of the most common setup errors, usually surfacing as a generic "redirect URI mismatch" error from the provider.
Requesting specific additional scopes
return Socialite::driver('facebook')->scopes(['email', 'public_profile'])->redirect();
Some providers don't return an email address by default unless the appropriate scope is explicitly requested — Facebook specifically requires the email scope to be requested, since without it, $socialUser->getEmail() can return null even for a user with a verified email on the platform.
Handling a user who denies the permission request
Route::get('/auth/{provider}/callback', function (string $provider) {
try {
$socialUser = Socialite::driver($provider)->user();
} catch (\Exception $e) {
return redirect('/login')->with('error', 'Login was cancelled or failed.');
}
// ...
});
A user declining the permission request on the provider's own consent screen results in an exception when Laravel attempts to retrieve their profile — wrapping this in a try/catch avoids an unhandled error page and instead returns the user to a normal login screen with a clear message.