Laravel 5.2 Socialite Twitter Login (Part 2)

This is part two of the Laravel 5.2 socialite auth tutorial. In the first part we installed socialite plugin, prepared configuration, made a service which will handle creating users with social accounts and made it work with facebook.

Configuring Twitter App

This time we will try to add an option to login with twitter.

Like with facebook, you need to use twitter panel for developers where you need to create the app. Go to the Twitter Apps page, and click Create New App.

Creating new app

Enter the application name and description. For website use http://placeholder.com or any other fully qualified url that can pass validation. For production you can put your real website address. For development we will use placeholder address.

New App information

Configuring Socialite

Click on the Keys and Access Tokens tab. With this we can configure Socialite.

Copy Consumer Key (API Key) to client_id, Consumer Secret (API Secret) to client_secret. For redirect we will use already built route but with additional parameter so we will be able to make distinction between different providers (in this case facebook and twitter). In the redirect field enter http://localhost:8000/callback/twitter.

'twitter' => [
    'client_id' => 'jvVgZoMJFDGF0nuSRFzrE4jO3',
    'client_secret' => 'onPJd84dU1ZrHgsGmWCFBI4iv5octmWDLQooJ1TZix1T34ttjf',
    'redirect' => 'http://localhost:8000/callback/twitter',
],

Using more than one provider

Currently we don't have the route we defined above in our app, so let's make it. Change callback route definition to this:

Route::get('/callback/{provider}', 'SocialAuthController@callback');

And callback method in SocialAuthController needs to use that new parameter to tell socialite what driver to use.

public function callback(SocialAccountService $service, $provider)
{
    // Important change from previous post is that I'm now passing
    // whole driver, not only the user. So no more ->user() part
    $user = $service->createOrGetUser(Socialite::driver($provider));

    auth()->login($user);

    return redirect()->to('/home');
}

Small change to the SocialAccountService. It will receive concrete provider, so we dont need to pass $provider parameter to the createOrGetUser method. We will use class name of the provider to differentiate between them before we save SocialAccount to the database.

<?php

namespace App;

use Laravel\Socialite\Contracts\Provider;

class SocialAccountService
{
    public function createOrGetUser(Provider $provider)
    {

        $providerUser = $provider->user();
        $providerName = class_basename($provider); 

        $account = SocialAccount::whereProvider($providerName)
            ->whereProviderUserId($providerUser->getId())
            ->first();

        if ($account) {
            return $account->user;
        } else {

            $account = new SocialAccount([
                'provider_user_id' => $providerUser->getId(),
                'provider' => $providerName
            ]);

            $user = User::whereEmail($providerUser->getEmail())->first();

            if (!$user) {

                $user = User::create([
                    'email' => $providerUser->getEmail(),
                    'name' => $providerUser->getName(),
                ]);
            }

            $account->user()->associate($user);
            $account->save();

            return $user;

        }

    }
}

Now we don't have a valid callback for facebook, lets change that:

'facebook' => [
    'client_id' => '690344774435367',
    'client_secret' => 'ebc50d3fd1d2f7286e02d247e5751ef4',
    'redirect' => 'http://localhost:8000/callback/facebook',
],

To allow users to choose with what network they want to login, we need to make distinction between redirects. Similar to the callback change, we will change routes.php and SocialAuthController's redirect method.

    Route::get('/redirect/{provider}', 'SocialAuthController@redirect');

Controller:

public function redirect($provider)
{
    return Socialite::driver($provider)->redirect();    
}

Now we will add Twitter Login link and change FB Login link to use new route.

<p>
    <a href="redirect/facebook">FB Login</a>
    <a href="redirect/twitter">Twitter Login</a>
</p>

Logi page with twitter option

And that is all. Click on the Twitter Login and you will be redirected back and logged in.

Next useful thing that comes to my mind is how to merge two or more social accounts into one.

Update: I added a comment in one of the code snippets to make changes from the previous post more visible.

Author

I plan to write more articles about common laravel components. If you are interested let’s stay in touch.
comments powered by Disqus