Login to Your Laravel App With Twitter / X Using Socialite

Allowing users to use their Twitter / X account to log into your Laravel application adds a lot of convenience for your users.

In this step-by-step guide, I’ll show you how to quickly add a ‘Login With Twitter’ option to your Laravel application using the Laravel Socialite package.

To speed up the process of building this feature, I’ll be using Laravel Jetstream to generate authentication scaffolding for us. If you have an existing application or prefer a different setup, you can easily adapt these steps as well.

Step 1: Install Laravel

If you haven’t already, create a new Laravel project using Composer:

composer create-project --prefer-dist laravel/laravel twitter-login-app

Navigate to your project directory:

cd twitter-login-app

Step 2: Install Jetstream

Now, let’s install Laravel Jetstream to take advantage of its scaffolding for adding the Twitter login feature. After completing this step you’ll have a working login form and a dashboard which is only accessible when logged in.

Execute the following artisan command:

composer require laravel/jetstream

Publish Jetstream’s assets and run its installation:

php artisan jetstream:install livewire

Follow the prompts to configure Jetstream according to your preferences.

Step 3: Install Socialite

Next, we’ll install the Laravel Socialite package using Composer and migrate the database tables it needs by running:

composer require laravel/socialite
php artisan migrate

Step 4: Starting the Local Application

Note that we won’t be running php artisan serve this time to launch our local site, as it uses http://localhost:8000 and Twitter Developer Portal requires us to create apps on an HTTPS-secured domain.

To ensure that your Laravel site can be accessed over HTTPS, you have two options:

  1. Run your site on a local domain, with HTTPS, on a test domain like for example: https://your-site.test

You can achieve this using tools such as:

  1. Running Your Site on a Local Domain with HTTPS via ngrok:

Ngrok is a third-party tool that allows HTTPS access to your local site. To use it, install ngrok from their site (it has a free version), and then run the following commands:

php artisan serve
ngrok http 8000

Your terminal will display an HTTPS URL, which you can use in your .env file and on the Twitter Developer Portal later. Please note that if you use this method, the Jetstream CSS and JS may appear distorted. You can fix this by making changes to app/Http/Middleware/TrustProxies.php as follows:

app/Http/Middleware/TrustProxies.php
<?php
namespace App\Http\Middleware;

use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;

class TrustProxies extends Middleware
{
    protected $proxies = '*'; // changed from default ''
    // keep the rest unchanged ...
}

Regardless of the option you choose, please test it by opening your site and clicking the login link. If the form displays correctly, proceed to step 5.

Step 5: Create Twitter App Credentials

To create our Twitter app and receive the app credentials open the Twitter Developer Portal and sign up or log in.

There you can follow these steps to create your app:

  1. On the dashboard page Click “Add App”
  2. Fill in a App name
  3. Copy the API Key and Secret and keep them for later use
  4. Click “Set up” on the “App details” page
  5. Fill in the form and make sure to:
    • Check “Read”
    • Check “Request email from users”
    • As “Type of App” check “Web App, Automated App or Bot”
    • Fill in “Callback URI / Redirect URI” with: https://your-site.test/auth/twitter/callback
    • Fill in “Website URL with: https://your-site.test
    • Fill in a terms of service link, unless it’s for production use it can be any URL, even non-existent, like: https://your-site.test/terms-of-service
    • Fill in a privacy policy link, unless it’s for production use it can be any URL, even non-existent, like: https://your-site.test/privacy-policy
  6. Save your settings

To guide you through the steps listed above, I’ve included screenshots of the entire process below:

1. Screenshot: Twitter / X Developer Portal Showing the “Add App” Button we Need to Click
2. Screenshot: Twitter Developer Portal Asking for our App Name
3. Screenshot: The Page Where we Copy Our API Key and API Key Secret
4. Screenshot: The App Details Page Where we Click “Set up”
5a. Screenshot: First Part of the App User Authentication Form
5b. Screenshot: Second and Final Part of the App User Authentication Form

Make sure you have the API Key and Secret, and move on to the next step.

Step 6: Add Twitter App Credentials to the Config

In your Laravel application, open the config/services.php file. Add the Twitter credentials you obtained in the previous step:

config/services.php
'twitter' => [
    'client_id' => env('TWITTER_CLIENT_API_KEY'),
    'client_secret' => env('TWITTER_CLIENT_API_SECRET_KEY'),
    'redirect' => env('TWITTER_CALLBACK_URL'),
],

Make sure to set these values in your .env file:

.env
TWITTER_CLIENT_API_KEY=YOUR_CLIENT_ID
TWITTER_CLIENT_API_SECRET_KEY=YOUR_CLIENT_SECRET
TWITTER_CALLBACK_URL=https://your-domain.test/auth/twitter/callback

Step 7: Add Database Column to Store twitter_id

Extend your user database by creating a migration to add a twitter_id column:

php artisan make:migration add_twitter_id_to_users

In the generated migration file, modify the up and down methods as follows:

database/migrations/2023_10_06_171219_add_twitter_id_to_users.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table) {
            Schema::table('users', function (Blueprint $table) {
                $table->string('twitter_id')->after('remember_token')->nullable()->unique();
            });
        });
    }

    public function down(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('twitter_id');
        });
    }
};

Run the following artisan command to add our new column:

php artisan migrate

Step 8: Modify the User Model

In your User model (typically located at app/Models/User.php), make the twitter_id column fillable for mass assignment by adding it to the $fillable array.

app/Models/User.php
<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Laravel\Jetstream\HasProfilePhoto;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens;
    use HasFactory;
    use HasProfilePhoto;
    use Notifiable;
    use TwoFactorAuthenticatable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'twitter_id',  // Add 'twitter_id' to the fillable array.
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
        'two_factor_recovery_codes',
        'two_factor_secret',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    /**
     * The accessors to append to the model's array form.
     *
     * @var array<int, string>
     */
    protected $appends = [
        'profile_photo_url',
    ];
}

Step 9: Create TwitterController

Add a controller named TwitterController to your application by running the Artisan command:

php artisan make:controller TwitterController

In TwitterController.php, add the methods redirectToTwitter and handleTwitterCallback which will handle Twitter login and callback.

app/Models/User.php
<?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 TwitterController extends Controller
{
    /**
     * Redirect to Twitter
     *
     * @return RedirectResponse
     */
    public function redirectToTwitter(): RedirectResponse
    {
        return Socialite::driver('twitter')->redirect();
    }

    /**
     * Handle Twitter authentication callback
     *
     * @return RedirectResponse
     */
    public function handleTwitterCallback(): RedirectResponse
    {
        try
        {
            $user = Socialite::driver('twitter')->user();
        }
        catch (Throwable $e) {
            return redirect(route('login'))->with('error', 'Twitter authentication failed.');
        }

        $existingUser = User::where('twitter_id', $user->id)->first();

        if ($existingUser){
            Auth::login($existingUser);
        } else {
            $newUser = User::updateOrCreate([
                'email' => $user->email
            ], [
                'name' => $user->name,
                'twitter_id'=> $user->id,
                'password' => bcrypt(request(Str::random())) // Set a random password
            ]);
            Auth::login($newUser);
        }
        return redirect()->intended('dashboard');
    }
}

Step 10: Add Routes

Add routes for Twitter login and callback URL’s to your routes/web.php file, like shown below:

routes/web.php
<?php

use App\Http\Controllers\TwitterController;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
    return view('dashboard');
})->name('dashboard');

Route::controller(TwitterController::class)->group(function(){
    Route::get('auth/twitter', 'redirectToTwitter')->name('auth.twitter');
    Route::get('auth/twitter/callback', 'handleTwitterCallback');
});

Step 11: Update Login Blade File

In this step we will update the login page UI to include a Twitter login button.

Edit the resources/views/auth/login.blade.php to add a button to sign in with Twitter, as shown in the code sample below:

resources/views/auth/login.blade.php
<x-guest-layout>
    <x-authentication-card>
        <x-slot name="logo">
            <x-authentication-card-logo />
        </x-slot>

        <x-validation-errors class="mb-4" />

        @if (session('status'))
            <div class="mb-4 font-medium text-sm text-green-600">
                {{ session('status') }}
            </div>
        @endif

        <form method="POST" action="{{ route('login') }}">
            @csrf

            <div>
                <x-label for="email" value="{{ __('Email') }}" />
                <x-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus autocomplete="username" />
            </div>

            <div class="mt-4">
                <x-label for="password" value="{{ __('Password') }}" />
                <x-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="current-password" />
            </div>

            <div class="block mt-4">
                <label for="remember_me" class="flex items-center">
                    <x-checkbox id="remember_me" name="remember" />
                    <span class="ml-2 text-sm text-gray-600">{{ __('Remember me') }}</span>
                </label>
            </div>

        {{-- Begin custom changes in login.blade.php --}}
        <div class="flex mt-4 justify-between">
            <a href="{{ route('auth.twitter') }}" style="background-color: #183153" class="inline-flex items-center px-2 float-left py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 focus:bg-gray-700 active:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition ease-in-out duration-150 h-10 px-2 py-2 mt-2 font-semibold text-xs text-white float-left transition-colors duration-150 rounded-lg uppercase focus:shadow-outline0 bg-gray-800 hover:bg-gray-700 focus:bg-gray-700 active:bg-gray-900">
                <img src="https://www.cdnlogo.com/logos/t/96/twitter-icon.svg" class="w-4 p-1 mr-2">
                Login with Twitter
            </a>
            <x-button class="h-10 px-2 py-2 m-2 ml-6 font-semibold text-xs text-white float-right transition-colors duration-150 rounded-lg uppercase focus:shadow-outline0 bg-gray-800 hover:bg-gray-700 focus:bg-gray-700 active:bg-gray-900">
                {{ __('Log in') }}
            </x-button>
        </div>

        <div class="block mt-4 text-right">
            @if (Route::has('password.request'))
                <a class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" href="{{ route('password.request') }}">
                    {{ __('Forgot your password?') }}
                </a>
            @endif
        </div>
        {{-- End custom changes in login.blade.php --}}
        </form>
    </x-authentication-card>
</x-guest-layout>

Step 12: Testing Logging in With Twitter/X

  • Go to https://your-localsite.test/login to access the login form (or use ngrok url)
  • On the login page, click the newly added “Login with Twitter” button.
  • You are being directed to the Twitter permission window
  • Here, you can log into your Twitter account
  • After you’ve authorized the application, your TwitterLoginController will receive a callback with the user data.
  • The controller creates or updates a user and adds the Twitter ID to it if not present already.
  • Finally, you’ll be automatically redirected to the intended dashboard.

To guide you through the testing I’ve included screenshots of the entire process below:

The Login Form Showing the Added Login With Twitter Button
Twitter / X Login and Authorize Application Window
Twitter Redirecting to Your Local Laravel Site
After Successfully Logging in With Twitter / X In We’re Redirected to the Jetstream Dashboard

Conclusion

Congratulations! You’ve successfully added the option for users to log into your app using their existing Twitter/X account. This makes your Laravel application more accessible and user-friendly.

If you have any questions or need further assistance, feel free to explore the provided references for more details on Laravel Jetstream and Laravel Socialite. Happy coding!

References

This entry is part 3 of 4 in the series Authenticating With Laravel Socialite

  1. Adding Login With Google to Your Laravel App Using Socialite
  2. Login to Your Laravel App With Facebook Using Socialite
  3. Login to Your Laravel App With Twitter / X Using Socialite
  4. Login to Your Laravel App With GitHub Using Socialite

Johan van den Broek

Johan is the creator of laracoding.com. As a child, he began tinkering with various programming languages, many of which have been long forgotten today. Currently, he works exclusively with PHP and Laravel, and his passion for programming remains to this day.

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Posts