Thư viện Socialite trong Laravel để xử lý đăng nhập social
Contents
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
Cách lấy các social tham khảo bài viết:
Xử lý đăng nhập bằng Google
Xử lý đăng nhập twitter
Xử lý đăng nhập line
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:
- https://stackoverflow.com/questions/64841743/clientexception-client-error-get-https-www-googleapis-com-plus-v1-people-me
- https://github.com/laravel/socialite/pull/283/files#diff-1cb4bfeddd8f4303d9f681256014bb9da048ea01f2b2e273e3b2600a52cd38f6
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), ]); } }