To add Login with Facebook to Laravel 13, install Laravel Socialite, create an app in Meta for Developers, add its keys to config/services.php and write two routes: one that redirects to Facebook and one that handles the callback. In the callback you find or create a local user and log them in. This guide covers each step, including the points that usually cause errors.

Targets: Laravel 13 (PHP 8.3 to 8.5) and laravel/socialite. Socialite ships a built-in facebook driver.

Step 1: Install Socialite

composer require laravel/socialite 

Step 2: Create a Facebook app

  1. Open Meta for Developers and create an app. Choose a use case that includes Facebook Login.
  2. Add the Facebook Login product to the app.
  3. Under Facebook Login settings, add your callback URL to Valid OAuth Redirect URIs, for example http://localhost:8000/auth/facebook/callback.
  4. From the app settings, copy the App ID and App Secret.

Meta changes the dashboard layout from time to time, so use the names above as a guide and follow the labels you see. Keep the app in development mode while testing; only the app's admins and testers can log in until you publish it.

Step 3: Add the credentials

Put the values in .env:

FACEBOOK_CLIENT_ID=your-app-id FACEBOOK_CLIENT_SECRET=your-app-secret FACEBOOK_REDIRECT_URI=http://localhost:8000/auth/facebook/callback 

Then register them in config/services.php:

'facebook' => [ 'client_id' => env('FACEBOOK_CLIENT_ID'), 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), 'redirect' => env('FACEBOOK_REDIRECT_URI'), ], 

The redirect value must match the URI you saved in the Meta dashboard exactly, including the scheme, host, port and path.

Step 4: Store the Facebook ID on users

Create a migration that adds a unique facebook_id column and makes the password optional, because social users have no password:

php artisan make:migration add_facebook_id_to_users_table --table=users 
public function up(): void { Schema::table('users', function (Blueprint $table) { $table->string('facebook_id')->nullable()->unique()->after('email'); $table->string('password')->nullable()->change(); }); } public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('facebook_id'); }); } 

Add facebook_id to the $fillable array on the User model, then run php artisan migrate.

Step 5: Create the controller

php artisan make:controller FacebookAuthController 
<?php namespace App\Http\Controllers; use App\Models\User; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Str; use Laravel\Socialite\Facades\Socialite; use Throwable; class FacebookAuthController extends Controller { public function redirect(): RedirectResponse { return Socialite::driver('facebook')->redirect(); } public function callback(): RedirectResponse { try { $facebookUser = Socialite::driver('facebook')->user(); } catch (Throwable $e) { report($e); return redirect('/login')->withErrors(['email' => 'Facebook login failed. Please try again.']); } if (! $facebookUser->getEmail()) { return redirect('/login')->withErrors(['email' => 'Facebook did not share an email address.']); } $user = User::updateOrCreate( ['facebook_id' => $facebookUser->getId()], [ 'name' => $facebookUser->getName() ?: 'Facebook user', 'email' => $facebookUser->getEmail(), 'email_verified_at' => now(), 'password' => Str::password(32), ] ); Auth::login($user, remember: true); return redirect()->intended('/dashboard'); } } 

The callback uses the Facebook ID as the lookup key, handles a failed login, and refuses accounts without an email address. Facebook users can sign up with a phone number only, or deny the email permission, so always check.

One security point: if a user already registered with the same email by password, updateOrCreate on facebook_id would try to create a second user with that email and fail on the unique index. For a real product decide whether to link the accounts after the user confirms ownership.

Step 6: Add the routes

use App\Http\Controllers\FacebookAuthController; use Illuminate\Support\Facades\Route; Route::get('/auth/facebook/redirect', [FacebookAuthController::class, 'redirect'])->name('facebook.redirect'); Route::get('/auth/facebook/callback', [FacebookAuthController::class, 'callback']); 

Link to it from your login page:

<a href="{{ route('facebook.redirect') }}">Continue with Facebook</a> 

How do I test the login?

  1. Start the app with php artisan serve and open the login page.
  2. Click the Facebook link and approve the permissions with an admin or tester account.
  3. After the redirect you should land on /dashboard and see a new row in the users table with a facebook_id.

Common mistakes

  • Redirect URI mismatch: the URI in .env and in the Meta dashboard must be identical.
  • App not live: a normal user who is not a tester cannot log in while the app is in development mode.
  • Null email: not every Facebook account returns an email. Handle it.
  • Password column not nullable: inserts fail for social users unless you change it or set a random password, as the example does.
  • Cached config: after editing services.php or .env run php artisan config:clear.

FAQ

Does Socialite support Facebook out of the box?

Yes. Facebook is one of the built-in drivers, along with X, LinkedIn, Google, GitHub, GitLab, Bitbucket and Slack.

Do I need the stateless() method?

Only for stateless apps such as pure APIs without sessions. A normal web app can use the default flow.

How do I request more permissions?

Call scopes([...]) before redirect(). Extra permissions may require Meta app review before they work for the public.

References

Originally published on yasiramin.dev.