Laravel Socialite provides a simple, fluent interface for OAuth authentication with Facebook, Google, Twitter, GitHub, and many other providers.
Installing Socialite
bashcomposer require laravel/socialite
Configuration
Add credentials in config/services.php:
php'github' => [ 'client_id' => env('GITHUB_CLIENT_ID'), 'client_secret' => env('GITHUB_CLIENT_SECRET'), 'redirect' => env('GITHUB_REDIRECT_URI'), ], 'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => env('GOOGLE_REDIRECT_URI'), ],
Add to .env:
envGITHUB_CLIENT_ID=your-client-id GITHUB_CLIENT_SECRET=your-client-secret GITHUB_REDIRECT_URI=http://localhost:8000/auth/github/callback GOOGLE_CLIENT_ID=your-client-id GOOGLE_CLIENT_SECRET=your-client-secret GOOGLE_REDIRECT_URI=http://localhost:8000/auth/google/callback
OAuth Flow
1. User clicks "Login with GitHub"
┌──────────────────────────────────────────┐
│ Your App → Redirect to GitHub │
└──────────────────────────────────────────┘
│
▼
2. User authorizes your app on GitHub
┌──────────────────────────────────────────┐
│ GitHub → Shows authorization screen │
│ User clicks "Authorize" │
└──────────────────────────────────────────┘
│
▼
3. GitHub redirects back with authorization code
┌──────────────────────────────────────────┐
│ GitHub → Your callback URL │
│ ?code=abc123... │
└──────────────────────────────────────────┘
│
▼
4. Your app exchanges code for user data
┌──────────────────────────────────────────┐
│ Socialite::driver('github')->user() │
│ Returns: name, email, avatar, etc. │
└──────────────────────────────────────────┘
│
▼
5. Create or log in user
┌──────────────────────────────────────────┐
│ Find/create user, log them in │
└──────────────────────────────────────────┘
Defining Routes
php// routes/web.php use App\Http\Controllers\Auth\SocialiteController; Route::get('/auth/{provider}', [SocialiteController::class, 'redirect']) ->name('socialite.redirect'); Route::get('/auth/{provider}/callback', [SocialiteController::class, 'callback']) ->name('socialite.callback');
The Controller
php<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Str; use Laravel\Socialite\Facades\Socialite; class SocialiteController extends Controller { /** * Supported providers. */ protected array $providers = ['github', 'google', 'facebook']; /** * Redirect to OAuth provider. */ public function redirect(string $provider) { if (! in_array($provider, $this->providers)) { abort(404); } return Socialite::driver($provider)->redirect(); } /** * Handle OAuth callback. */ public function callback(string $provider) { if (! in_array($provider, $this->providers)) { abort(404); } try { $socialUser = Socialite::driver($provider)->user(); } catch (\Exception $e) { return redirect()->route('login') ->with('error', 'Unable to authenticate with ' . ucfirst($provider)); } // Find or create user $user = User::updateOrCreate( [ 'provider' => $provider, 'provider_id' => $socialUser->getId(), ], [ 'name' => $socialUser->getName(), 'email' => $socialUser->getEmail(), 'avatar' => $socialUser->getAvatar(), 'provider_token' => $socialUser->token, 'provider_refresh_token' => $socialUser->refreshToken, 'password' => bcrypt(Str::random(24)), // Random password ] ); Auth::login($user, remember: true); return redirect()->intended('/dashboard'); } }
Database Migration
php// Add social auth columns to users table public function up(): void { Schema::table('users', function (Blueprint $table) { $table->string('provider')->nullable(); $table->string('provider_id')->nullable(); $table->string('provider_token')->nullable(); $table->string('provider_refresh_token')->nullable(); $table->string('avatar')->nullable(); $table->string('password')->nullable()->change(); // Make nullable for social users $table->unique(['provider', 'provider_id']); }); }
The Socialite User Object
php$socialUser = Socialite::driver('github')->user(); $socialUser->getId(); // Provider's user ID $socialUser->getNickname(); // Username (if available) $socialUser->getName(); // Full name $socialUser->getEmail(); // Email address $socialUser->getAvatar(); // Avatar URL $socialUser->token; // Access token $socialUser->refreshToken; // Refresh token (if available) $socialUser->expiresIn; // Token expiration (seconds) // Raw data from provider $socialUser->user; // Full response array $socialUser->user['login']; // Access specific fields
Handling Existing Users
phppublic function callback(string $provider) { $socialUser = Socialite::driver($provider)->user(); // Check if user exists with this email $existingUser = User::where('email', $socialUser->getEmail())->first(); if ($existingUser) { // Link social account to existing user if (! $existingUser->provider) { $existingUser->update([ 'provider' => $provider, 'provider_id' => $socialUser->getId(), ]); } Auth::login($existingUser); } else { // Create new user $user = User::create([ 'name' => $socialUser->getName(), 'email' => $socialUser->getEmail(), 'provider' => $provider, 'provider_id' => $socialUser->getId(), ]); Auth::login($user); } return redirect()->intended('/dashboard'); }
View Integration
blade<div class="social-login"> <a href="{{ route('socialite.redirect', 'github') }}" class="btn btn-github"> <svg>...</svg> Login with GitHub </a> <a href="{{ route('socialite.redirect', 'google') }}" class="btn btn-google"> <svg>...</svg> Login with Google </a> </div>
Additional Scopes
php// Request additional permissions return Socialite::driver('github') ->scopes(['read:user', 'user:email', 'repo']) ->redirect(); // Stateless for API usage $user = Socialite::driver('github')->stateless()->user();