Muhammad Yasir Amin

Loading websiteโ€ฆ

More from Muhammad Yasir Amin

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Subscribe on YouTube

Laravel 13 Socialite Login with Facebook: Step-by-Step Guide

๐Ÿ› ๏ธ Laravel Tutorials4 min read

Laravel 13 Socialite Login with Facebook: Step-by-Step Guide

Muhammad Yasir Amin

Muhammad Yasir Amin

Senior Full Stack Engineerโ€ขNov 12, 2026
Laravel 13 Socialite Login with Facebook: Step-by-Step Guide

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

Code
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:

Code
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:

JavaScript
'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:

Code
php artisan make:migration add_facebook_id_to_users_table --table=users
JavaScript
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

Code
php artisan make:controller FacebookAuthController
JavaScript
<?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

CSS
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:

HTML / XML
<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

Article Index & Topic Tags
LaravelSocialiteAuthenticationFacebook

YouTube Channel

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Muhammad Yasir Amin
Available for Contracts
Author & Solutions Architect

Senior Full Stack Engineer

Independent Senior Full Stack Engineer working on Laravel, React and Next.js applications, APIs and delivery workflows.

Laravel & PHP ApplicationsReact & Next.js InterfacesREST APIs & IntegrationsDatabase Queries & DebuggingDocker Development WorkflowsClear Scope & Handover
Discuss Your Next Step

What Does Your Application Need Next?

Share your current system, the problem you want to solve and what a useful result looks like. We can identify the right starting point and agree on a practical scope.

Technical Audit

Find the Next Useful Fix

Application Development

Scoped, Reviewable Milestones

Ongoing Support

Agreed Capacity and Priorities

Share your goals, current stack and requirements before the call.