Registration & Login using Social Media in Laravel (Socialite Package)

With the growing usage of social media, Social Media Registration and authentication are important for any web applications. The advantage of having them is users can Register/Login into your application with the click of a button and don’t have to remember a new credential for the application.

In this blog, you will look into integrating social media Registration/Login in your Laravel application using Laravel Official package – Socialite.

Socialite package currently supports authentication with Facebook, Twitter, LinkedIn, Google, GitHub, and Bitbucket. For other adapaters, you can check out this package, which provides MANY adapters.

Step1: Installation of socialite package

Install socialite using the below command:

composer require laravel/socialite 1 composer require laravel / socialite

Step2: Configuration

In order for oAuth to work add the credentials of oAuth service provider in your applications config/services.php .

For example, if you want to add for Facebook and GitHub it will look like this:

GitHub 'github' => [ 'client_id' => env('GITHUB_CLIENT_ID'), 'client_secret' => env('GITHUB_CLIENT_SECRET'), 'redirect' => '/provider/github/callback', ], 1 2 3 4 5 'github' = > [ 'client_id' = > env ( 'GITHUB_CLIENT_ID' ) , 'client_secret' = > env ( 'GITHUB_CLIENT_SECRET' ) , 'redirect' = > '/provider/github/callback' , ] ,

Facebook 'facebook' => [ 'client_id' => env('FACEBOOK_CLIENT_ID'), 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), 'redirect' => '/provider/facebook/callback', ], 1 2 3 4 5 'facebook' = > [ 'client_id' = > env ( 'FACEBOOK_CLIENT_ID' ) , 'client_secret' = > env ( 'FACEBOOK_CLIENT_SECRET' ) , 'redirect' = > '/provider/facebook/callback' , ] ,

Step3: Migrations

You will need a table to store the provider’s id for each user. This will help us to identify a user from their provider’s id.

Our migration Up function will look like this:

Migration for social_accounts table. /** * Run the migrations. * * @return void */ public function up() { Schema::create('social_accounts', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->string('provider_user_id'); //Store the provider's user id. $table->enum('provider', ['facebook', 'twitter', 'linkedin', 'github']); //Store the provider. $table->timestamps(); $table->foreign('user_id')->references('id')->on('users'); }); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /** * Run the migrations. * * @return void */ public function up ( ) { Schema :: create ( 'social_accounts' , function ( Blueprint $ table ) { $ table -> increments ( 'id' ) ; $ table -> integer ( 'user_id' ) -> unsigned ( ) ; $ table -> string ( 'provider_user_id' ) ; //Store the provider's user id. $ table -> enum ( 'provider' , [ 'facebook' , 'twitter' , 'linkedin' , 'github' ] ) ; //Store the provider. $ table -> timestamps ( ) ; $ table -> foreign ( 'user_id' ) -> references ( 'id' ) -> on ( 'users' ) ; } ) ; }

Note: Instead of defining another table you can add columns like facebook_id , github_id in users table itself. But with increasing number of providers, the columns will increase. I prefer having a separate table to keep things simple while checking during login, as we will look into it below steps.

Step4: Defining function & Adding routes.

You will need 2 functions for socialite to work:

To redirect to the oAuth service provider from our application with the credentials To handle the callback from the service provider where we will retrieve users information.

In Auth\LoginController.php define a function to redirect to the provider:

/** * Redirect the user to the Provider authentication page. * * @return \Illuminate\Http\Response */ public function redirectToProvider($provider) { return Socialite::driver($provider)->redirect(); } 1 2 3 4 5 6 7 8 9 /** * Redirect the user to the Provider authentication page. * * @return \Illuminate\Http\Response */ public function redirectToProvider ( $ provider ) { return Socialite :: driver ( $ provider ) -> redirect ( ) ; }

And the function to handle callback from the provider. This function will do multiple things:

Check if the user is already registered by checking for provider_user_id with $providerUser->getId() If the user is already registered then redirect to the intended page. If the user is not present, add the user details in users table and also add the provider’s id into social_accounts table.

/** * Obtain the user information from the Provider. * * @return \Illuminate\Http\Response */ public function handleProviderCallback($provider) { $user = $this->createOrGetUser(Socialite::driver($provider)->stateless()->user(), $provider); Auth::login($user); return redirect()->to('/home'); } /** * Create or get a user based on provider id. * * @return Object $user */ private function createOrGetUser($providerUser, $provider) { $account = SocialAccount::where('provider', $provider) ->where('provider_user_id', $providerUser->getId()) ->first(); if ($account) { //Return account if found return $account->user; } else { //Check if user with same email address exist $user = User::where('email', $providerUser->getEmail())->first(); //Create user if dont'exist if (!$user) { $user = User::create([ 'email' => $providerUser->getEmail(), 'name' => $providerUser->getName() ]); } //Create social account $user->social_accounts()->create([ 'provider_user_id' => $providerUser->getId(), 'provider' => $provider ]); return $user; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 /** * Obtain the user information from the Provider. * * @return \Illuminate\Http\Response */ public function handleProviderCallback ( $ provider ) { $ user = $ this -> createOrGetUser ( Socialite :: driver ( $ provider ) -> stateless ( ) -> user ( ) , $ provider ) ; Auth :: login ( $ user ) ; return redirect ( ) -> to ( '/home' ) ; } /** * Create or get a user based on provider id. * * @return Object $user */ private function createOrGetUser ( $ providerUser , $ provider ) { $ account = SocialAccount :: where ( 'provider' , $ provider ) -> where ( 'provider_user_id' , $ providerUser -> getId ( ) ) -> first ( ) ; if ( $ account ) { //Return account if found return $ account -> user ; } else { //Check if user with same email address exist $ user = User :: where ( 'email' , $ providerUser -> getEmail ( ) ) -> first ( ) ; //Create user if dont'exist if ( ! $ user ) { $ user = User :: create ( [ 'email' = > $ providerUser -> getEmail ( ) , 'name' = > $ providerUser -> getName ( ) ] ) ; } //Create social account $ user -> social_accounts ( ) -> create ( [ 'provider_user_id' = > $ providerUser -> getId ( ) , 'provider' = > $ provider ] ) ; return $ user ; } }

Add the related routes for them:

Note: Don’t include these routes in Auth Middleware.

Step5: Adding links in Registration/Login view:

In your registration and Login view add links for the providers you want to integrate.

For example, if you want facebook and gitHub, you will have to add the like this below:

<a class="btn btn-social btn-github" href="{{route('redirectToProvider', ['github'])}}"> <span class="fa fa-github"></span> Login with GitHub </a> <a class="btn btn-social btn-facebook" href="{{route('redirectToProvider', ['facebook'])}}"> <span class="fa fa-facebook"></span> Login with Facebook </a> 1 2 3 4 5 6 7 < a class = "btn btn-social btn-github" href = "{{route('redirectToProvider', ['github'])}}" > < span class = "fa fa-github" > < / span > Login with GitHub < / a > < a class = "btn btn-social btn-facebook" href = "{{route('redirectToProvider', ['facebook'])}}" > < span class = "fa fa-facebook" > < / span > Login with Facebook < / a >

If you’re using bootstrap you can include Bootstrap Social button for nice looking buttons.

With this your Social media login and Registration is ready!!

Try register and logging using your social media, it will work. In case it won’t check if you have added the correct client_id, client_secret and also provided a correct callback URL in your oAuth service provider app.

Having some other problem? feel free to ask below.

If you have a better way of doing any of the things mentioned above, please do comment below.