DEV Community

Scalia Abel
Scalia Abel

Posted on

Laravel Google Login with Socialite

Social login help simplifies registration and login for the end users. Socialite is a social login package provided by Laravel. This package allows us to seamlessly integrate social logins like Facebook, Twitter, Google and many more. The list of adapters that Socialite provides can be found here.

A Google Cloud Platform (GCP) account is required for this example.

Installation

First we need to scaffold our application with Laravel breeze. You can follow the steps provided here.

Once the scaffolding is done, we will need to install the socialite package into our application.



composer require laravel/socialite


Enter fullscreen mode Exit fullscreen mode

Setting Up Migrations

Let's create a table to store the user's socialite login.



php artisan make:migration CreateSocialiteLoginsTable


Enter fullscreen mode Exit fullscreen mode

Next, setup the columns for our socialite_logins table.



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

class CreateSocialiteLoginsTable extends Migration
{
    public function up(): void
    {
        Schema::create('socialite_logins', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->references('id')->on('users');
            $table->string('provider_id');
            $table->string('provider');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('socialite_logins');
    }
}


Enter fullscreen mode Exit fullscreen mode

The user_id column will be used to map the socialite logins to the users. The type of provider will be saved in the provider column, i.e google.

Considering that the users are not required to register, make sure to change the password column in our CreateUsersTable migration to nullable, .

Setting Up Models

Create a SocialiteLogin model.



php artisan make:model SocialiteLogin


Enter fullscreen mode Exit fullscreen mode

Since we are only implementing the Google authentication and a user can only have one Google account, the relationship between the SocialiteLogin model and User model is One-to-One.

If you feel like implementing another social login, you will need to change the relationship to Many-to-One.

Add the user_id, provider and provider_id field to the $fillable property in the SocialiteLogin model.



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class SocialiteLogin extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'provider',
        'provider_id'
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}


Enter fullscreen mode Exit fullscreen mode

Next, add the socialiteLogin relationship in the User model.



namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasFactory;
    use HasApiTokens;

    /**
     * The attributes that are mass assignable.
     *
     * @var string[]
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

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

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

    // change this to HasMany
    // if you are implementing
    // more than one social login
    public function socialiteLogin(): BelongsTo
    {
        return $this->belongsTo(SocialiteLogin::class);
    }
}


Enter fullscreen mode Exit fullscreen mode

Setting Up Google Cloud Platform

Login to a Google Cloud Platform account and select a project or create one. Click on the sidebar and navigate to the API and services -> OAuth Consent Screen.

Setting Up OAuth Consent Screen

We will be greeted by this screen.
OAuth Consent

Since we are authenticating external users, the user type that we'll be selecting is external.

Once we have selected the type of user, we will be redirected to the OAuth Consent Screen page. We are only required to fill in the app information section and the developer contact information.
App Information

The developer contact information will be your personal/work email.
Developer Contact

After setting up the app information, we will be setting up the scope of permission that is needed for our application. Click the add or remove scopes and select userinfo.email and userinfo.profile scope.
Scoped Permission

Click save and continue and setup the test user with an existing gmail account.

Setting Up Credentials

Proceed to the credentials tab located on the sidebar and create a new OAuth Client ID. The application type we are using is web application.

If you are developing with an SPA, you will need to setup the Authorized JavaScript Origin section. The http://localhost:3000 url is sufficient for this field.

The Authorized Redirect URIs is where we are going to handle the authentication of the user based on their email and profile. Our url will be http://127.0.0.1:8000/login/google/callback.
Credentials

Once we have created the credentials, we will be given the CLIENT_ID and CLIENT_SECRET values.

The credentials will be placed in services.php config and .env file.



// .env
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URI= // callback url

// services.php
'google' => [
   'client_id' => env('GOOGLE_CLIENT_ID'),
   'client_secret' => env('GOOGLE_CLIENT_SECRET'),
   'redirect' => env('GOOGLE_REDIRECT_URI'), // callback url
]


Enter fullscreen mode Exit fullscreen mode

Setting Up URL and Callback

Create a SocialiteLoginController controller. This controller will be consisting of two functions, redirectToProvider and handleProviderCallback



php artisan make:controller SocialiteLoginController


Enter fullscreen mode Exit fullscreen mode

Handling The Redirection and Callback

The redirectToProvider will only redirect the user to the google authentication page via the Socialite Driver.

Moving on to the handleProviderCallback. First we get the user from the Socialite driver. This user returns a variety of informations since the Google provider supports OAuth2.0.

In our case, we only need the user's email, name and id of the provider. We will be using Laravel's firstOrCreate method to identify if the user exists. If it does not, we will create a new user.

We will be using the same method for our SocialiteLogin model. We are doing this to ensure that there is no duplication for the socialite login since a user can only have one google account.

We can now safely authenticate the user by using Laravel's auth helper and redirect them to the dashboard.

The controller will look something like this.



namespace App\Http\Controllers;

use Laravel\Socialite\Facades\Socialite;

class SocialiteLoginController extends Controller
{
    public function redirectToProvider()
    {
        return Socialite::driver('google')->redirect();
    }

    public function handleProviderCallback()
    {
        $socialiteUser = Socialite::driver('google')->user();

        $user = User::firstOrCreate(
            [
                'email' => $socialiteUser->getEmail(),
            ],
            [
                'name' => $socialiteUser->getName(),
            ]
        );

        SocialiteLogin::firstOrCreate(
            [
                'user_id' => $user->id,
                'provider' => 'google',
            ],
            [
                'provider_id' => $socialiteUser->getId()
            ]
        );

        auth()->login($user);

        return redirect(route('dashboard'));
    }
}


Enter fullscreen mode Exit fullscreen mode

Setting Up The Route

Add the controller to the web.php route file.



// web.php
Route::get('/login/google', [SocialiteLoginController::class, 'redirectToProvider']);
Route::get('/login/google/callback', [SocialiteLoginController::class, 'handleProviderCallback']);


Enter fullscreen mode Exit fullscreen mode

The callback url needs to be the same with what we have setup in our Google Cloud Platform.

Updating the UI

We begin by starting our development server.



php artisan serve


Enter fullscreen mode Exit fullscreen mode

The UI is pretty simple compared to what we have done so far.

Since we will be doing a redirection, using an anchor tag makes more sense than using a button. Paste the code below to the login.blade.php.

Make sure to change the url accordingly



// login.blade.php
<a
  href="/login/google"
  class="ml-3 inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring ring-gray-300 disabled:opacity-25 transition ease-in-out duration-150"
>
   Login Google
</a>


Enter fullscreen mode Exit fullscreen mode

Click on the Login Google button to proceed to the Google OAuth Screen. After selecting a google account, we will be redirected to the dashboard after being authenticated.
Dashboard

Conclusion

Most of the providers that Socialite supports have the same implementation thus helping us reduce the boilerplate needed to be written and maintained.

Let me know if there are any questions or things that I can improve on.

Top comments (5)

Collapse
 
emilyngtt profile image
emilyngtt

Dear Scalia, Greetings from FPT Software Malaysia. We are hiring ReactJS Software Developers with competitive package. Please let me know if you are keen to know more.

Collapse
 
metallurgical profile image
Norlihazmey Ghazali

good sharing sca!

Collapse
 
scaabel profile image
Scalia Abel

Thanks!

Collapse
 
noelkalel profile image
noelkalel

is there some restriction about how many users can register in your app using google? or its infinite.

tnx for the articles. :)

Collapse
 
scaabel profile image
Scalia Abel

I'm not quite sure, but I think there's a limit on how many users you can have. You're welcome.