Thumbnail
Category: Lập trình

Thư viện Socialite trong Laravel để xử lý đăng nhập social

Date: October 11, 2022
40 views

1. Cài đặt

Đầu tiên, chúng ta add vào file composer.json .

 

composer require laravel/socialite


Sau đấy , ta sẽ cài đặt thư viện socialite Laravel\Socialite\SocialiteServiceProvider vào trong file config/app.php :


'providers' => [ 
  // Other service providers... 
  Laravel\Socialite\SocialiteServiceProvider::class, 
],


and alias


'aliases' => [ 
  'Socialite' => Laravel\Socialite\Facades\Socialite::class, 
],


Tiếp đến , chúng ta muốn sử dụng socialite nào thì chúng ta thêm credentials vào trong file config/service . Ví dụ ở đây chúng ta sử dụng facebook hay google . Chúng ta có thể sử dụng nhiều tài khoản xã hội cùng một lúc .


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


'google' => [
    'client_id' => '716438745047-ua94i3snt6s01i0ncn3u33j5h5rvu9rk.apps.googleusercontent.com',
    'client_secret' => '23zeZz1ya9syFMH4ggQM2e-p',
    'redirect' => 'http://localhost:8000/callback/google',
],
'twitter' => [
  	'client_id' => 'asTA03wBT',
  	'client_secret' => 'hn1xEWqMVIJSvmE',
  	'redirect' => 'http://laravel.dev/auth/twitter/callback',
],


Tham khảo: https://viblo.asia/p/tim-hieu-ve-socialite-trong-laravel-DbmemLOMGAg

2. Add Route


// SOCIAL
Route::group(['middleware' => ['web']], function () {
    Route::get('authorize/{provider}/redirect', [SocialAuthController::class, 'redirectToProvider']);
    Route::get('authorize/{provider}/callback', [SocialAuthController::class, 'handleProviderCallback']);
});


provider là google/twitter/line….

3. Tạo Controller


<?php


namespace App\Http\Controllers\Frontend\Api\v1;


use App\Http\Controllers\Controller;
use App\Models\Member;
use Illuminate\Http\Request;
use Socialite;


class SocialAuthController extends Controller
{
    public function redirectToProvider(Request $request, $provider)
    {
        $url = Socialite::driver($provider)->redirect()->getTargetUrl();
        return redirect($url);
    }


    public function handleProviderCallback(Request $request, $provider)
    {
        if ($provider == 'twitter') {
            $user = Socialite::driver($provider)->user();
        } else {
            $user = Socialite::driver($provider)->stateless()->user();
        }
        $data = [
            "social_id" => $user->id,
            "email" => $user->email,
            "avatar" => $user->avatar,
            "nick_name" => $user->name,
            "gender" => null,
            "birthday" => null,
            "auth_type" => $provider == 'google' ? 'GOOGLE' : ($provider == 'twitter' ? 'TWITTER' : ($provider == 'line' ? 'LINE' : '')),
        ];
        $data = (object)$data;
        return redirect("/auth/callback?social_id=$data->social_id&email=$data->email&avatar=$data->avatar&nick_name=$data->nick_name&gender=$data->gender&birthday=$data->birthday&auth_type=$data->auth_type");
    }


    public function handleProviderCallbackMobile(Request $request, $provider)
    {
        $user = Socialite::driver($provider)->stateless()->user();
        return redirect('/auth/callback/mobile?id=' . $user->id);
    }
}


4. Xử lý thêm nếu có đăng nhập bằng line

Chạy lệnh


composer require socialiteproviders/line


Trong config\app.php remove cái cũ thêm cái mới vào


'providers' => [
    // a whole bunch of providers
    // remove 'Laravel\Socialite\SocialiteServiceProvider',
    \SocialiteProviders\Manager\ServiceProvider::class, // add
];


'aliases' => [
    'Socialite' => \SocialiteProviders\Manager\ServiceProvider::class,
],


Vào file app/Providers/EventServiceProvider thêm event


protected $listen = [
    \SocialiteProviders\Manager\SocialiteWasCalled::class => [
        // ... other providers
        \SocialiteProviders\Line\LineExtendSocialite::class.'@handle',
    ],
];


Add services


'line' => [    
  'client_id' => env('LINE_CLIENT_ID'),  
  'client_secret' => env('LINE_CLIENT_SECRET'),  
  'redirect' => env('LINE_REDIRECT_URI') 
],


Usage


return Socialite::driver('line')->redirect();


5. Mô hình hoạt động

6. Kinh nghiệm

6.1 Lỗi xử lý get data google ở phiên bản cũ


Nguyên nhân là do google đã đổi api:

  • https://www.googleapis.com/plus/v1/people/me?  => https://www.googleapis.com/userinfo/v2/me?
  • Đồng thời cũng thay đổi key trả về.


Tham khảo thêm:


Cách khắc phục: Bạn vào vendor/laravel/socialite/src/Two/GooleProvider.php và thay đổi hàm getUserByToken và mapUserToObject như bên dưới.


<?php


namespace Laravel\Socialite\Two;


use Illuminate\Support\Arr;


class GoogleProvider extends AbstractProvider implements ProviderInterface
{
    /**
     * The separating character for the requested scopes.
     *
     * @var string
     */
    protected $scopeSeparator = ' ';


    /**
     * The scopes being requested.
     *
     * @var array
     */
    protected $scopes = [
        'openid',
        'profile',
        'email',
    ];


    /**
     * {@inheritdoc}
     */
    protected function getAuthUrl($state)
    {
        return $this->buildAuthUrlFromBase('https://accounts.google.com/o/oauth2/auth', $state);
    }


    /**
     * {@inheritdoc}
     */
    protected function getTokenUrl()
    {
        return 'https://accounts.google.com/o/oauth2/token';
    }


    /**
     * Get the POST fields for the token request.
     *
     * @param  string  $code
     * @return array
     */
    protected function getTokenFields($code)
    {
        return array_add(
            parent::getTokenFields($code),
            'grant_type',
            'authorization_code'
        );
    }


    /**
     * {@inheritdoc}
     */
    protected function getUserByToken($token)
    {
        $response = $this->getHttpClient()->get('https://www.googleapis.com/userinfo/v2/me?', [
            'query' => [
                'prettyPrint' => 'false',
            ],
            'headers' => [
                'Accept' => 'application/json',
                'Authorization' => 'Bearer ' . $token,
            ],
        ]);


        return json_decode($response->getBody(), true);
    }


    /**
     * {@inheritdoc}
     */
    protected function mapUserToObject(array $user)
    {
        $avatarUrl = $user['picture'];


        return (new User)->setRaw($user)->map([
            'id' => $user['id'], 'nickname' => Arr::get($user, 'name'), 'name' => $user['name'],
            'email' => Arr::get($user, 'email'), 'avatar' => $avatarUrl,
            'avatar_original' => preg_replace('/\?sz=([0-9]+)/', '', $avatarUrl),
        ]);
    }
}

Copyright © 2025 All Right Reserved