Laravel social login
Ở thời điểm viết bài mình sử dụng phiên bản Laravel 5.4 để thực hiện chức năng Social login cụ thể là Laravel 5.4 facebook login, các tài khoảng twitter, google, github,.. các bạn làm tương tự, mình sẽ nói ngắn gọi ở trong bài. 1. Vấn đề Input : Thực hiện chức năng đăng nhập bằng email ...
- Ở thời điểm viết bài mình sử dụng phiên bản Laravel 5.4 để thực hiện chức năng Social login cụ thể là Laravel 5.4 facebook login, các tài khoảng twitter, google, github,.. các bạn làm tương tự, mình sẽ nói ngắn gọi ở trong bài.
1. Vấn đề
Input:
- Thực hiện chức năng đăng nhập bằng email (cái này Laravel đã hỗ trợ sẵn nên mình bỏ qua) và cho phép đăng nhập bằng facebook.
Output:
- Tạo được tài khoản đăng nhập vào ứng dụng Laravel với tài khoản facebook.
2. Giải pháp
- Database:
- Bảng users với các trường name, email,..
- Bảng social_accounts với các trường user_id, provider_user_id, provider,...
- Ý tưởng: Ta sẽ tạo ra link cho phép người dùng click vào để login bằng tài khoản facebook, khi người dùng click vào nút này ta sẽ get thông tin của người dùng từ tài khoản facebook và insert vào database rồi thực hiện login. Ở đây laravel đã cung cấp sẵn cho ta package Socialite để giải quyết vẫn đề này.
- Thực hiện:
-
Cài đặt package socialite bằng composer
composer require laravel/socialite
-
Thêm providers vào file config/app.php
'providers' => [ // Other service providers... LaravelSocialiteSocialiteServiceProvider::class, ],
-
Thêm alias
'Socialite' => LaravelSocialiteFacadesSocialite::class,
-
Tiếp theo ta cần có một app facebook, bạn vào link này để tạo một app: https://developers.facebook.com/
-
Ta chọn Add a new app để tạo một app mới cho ứng dụng của ta, mình đã tạo sẵn app laravel54 với config như sau:
-
Ta lưu App ID, App Secret để tý thêm vào file config của ứng dụng và ta phải nhớ pubblic app này nhé:
-
OK phần app facebook, ta sẽ quay lại với ứng dụng laravel.
-
Đầu tiên ta cần thêm vào file config/services.php
'facebook' => [ 'client_id' => env('FACEBOOK_APP_ID'), 'client_secret' => env('FACEBOOK_APP_SECRET'), 'redirect' => env('FACEBOOK_APP_CALLBACK_URL'), ], 'github' => [ 'client_id' => env('GITHUB_APP_ID'), 'client_secret' => env('GITHUB_APP_SECRET'), 'redirect' => env('GITHUB_APP_CALLBACK_URL'), ], 'twitter' => [ 'client_id' => env('TWITTER_APP_ID'), 'client_secret' => env('TWITTER_APP_SECRET'), 'redirect' => env('TWITTER_APP_CALLBACK_URL'), ], 'google' => [ 'client_id' => env('GOOGLE_APP_ID'), 'client_secret' => env('GOOGLE_APP_SECRET'), 'redirect' => env('GOOGLE_APP_CALLBACK_URL'), ],
-
Nếu chỉ cần login bằng facebook thì ta chỉ cần thêm config services cho tài khoản facebook thôi, ở đây mình muốn nói đối với các tài khoản khác cũng tương tự. Các config này ta sẽ thêm sau vào file .env.
-
Tiếp theo ta tạo controller SocialAuthController
php artisan make:controller SocialAuthController
-
Thêm 2 method redirect và callback
namespace AppHttpControllers; use IlluminateHttpRequest; use AppHttpRequests; use AppServicesSocialAccountService; use IlluminateSupportFacadesLog; use Socialite; class SocialAuthController extends Controller { public function redirect($social) { return Socialite::driver($social)->redirect(); } public function callback($social) { $user = SocialAccountService::createOrGetUser(Socialite::driver($social)->user(), $social); auth()->login($user); return redirect()->to('/home'); } }
-
Service SocialAccountService để xử lý tạo mới user hoặc get user từ database, file này mình để trong thư mục appServices:
namespace AppServices; use LaravelSocialiteContractsUser as ProviderUser; use AppSocialAccount; use AppUser; class SocialAccountService { public static function createOrGetUser(ProviderUser $providerUser, $social) { $account = SocialAccount::whereProvider($social) ->whereProviderUserId($providerUser->getId()) ->first(); if ($account) { return $account->user; } else { $email = $providerUser->getEmail() ?? $providerUser->getNickname(); $account = new SocialAccount([ 'provider_user_id' => $providerUser->getId(), 'provider' => $social ]); $user = User::whereEmail($email)->first(); if (!$user) { $user = User::create([ 'email' => $email, 'name' => $providerUser->getName(), 'password' => $providerUser->getName(), ]); } $account->user()->associate($user); $account->save(); return $user; } } }
-
Đoạn getEmail() mình check nếu không get được thì sẽ set email bằng nickName do tài khoản twitter mà để private email thì ta sẽ không get được email, trường hợp này bạn có thể bắt người dùng update email rồi mới cho login cũng rất đơn giản. Hoặc ta sẽ set thêm cho bảng user trường email có thể null như sau:
$table->string('email')->unique()->nullable();
-
Tất nhiên là ta phải nhớ thêm bảng social_accounts và model cho nó:
php artisan make:migration create_social_accounts_table --create="social_accounts" php artisan make:model SocialAccount
-
Thêm vào file migrate
Schema::create('social_accounts', function (Blueprint $table) { $table->integer('user_id'); $table->string('provider_user_id'); $table->string('provider'); $table->timestamps(); });
-
Thêm quan hệ và model SocialAccount
namespace App; use IlluminateDatabaseEloquentModel; class SocialAccount extends Model { protected $fillable = ['user_id', 'provider_user_id', 'provider']; public function user() { return $this->belongsTo('AppUser'); } }
-
Thêm vào routes/web.php
Route::get('/redirect/{social}', 'SocialAuthController@redirect'); Route::get('/callback/{social}', 'SocialAuthController@callback');
-
Method redirect sẽ điều hướng người dùng đến facebook để xác nhận và method callback để xử lý gọi lại từ facebook.
-
Đến đây ta sẽ update file .env như sau:
FACEBOOK_APP_ID = 642423652634577 FACEBOOK_APP_SECRET = 91ffb713415e5e11f2a9f464a48c83b3 FACEBOOK_APP_CALLBACK_URL = http://localhost:8000/callback/facebook
-
Twitter, google, github ta cũng làm tương tự, nếu bạn muốn test thử thì có thể dùng luôn key của app mình đã tạo sẵn:
GITHUB_APP_ID = 79f02d69b8205fe2282b GITHUB_APP_SECRET = c82b3d193f3bf22b590d13ce47bd1e9da148026c GITHUB_APP_CALLBACK_URL = http://localhost:8000/callback/github TWITTER_APP_ID = 9C83R9zQ2TOIEFW5k9hUbKks2 TWITTER_APP_SECRET = DS5Si26a486MaqmBERsIcwJrjxVSYETm10KCeUhz5Tog6xBuyQ TWITTER_APP_CALLBACK_URL = http://localhost:8000/callback/twitter GOOGLE_APP_ID = 762749737436-vjblilaa7ijs906c3c9f5vgj7v3t78ks.apps.googleusercontent.com GOOGLE_APP_SECRET = 5drmbvkdCIXqOelFlMHaiExi GOOGLE_APP_CALLBACK_URL = http://localhost:8000/callback/google
-
Cuối cùng ta chỉ cần thêm link cho nút login bằng facebook và trải nghiệm thôi, chẳng hạn thêm <a href="redirect/facebook">FB Login</a> vào trang welcome.blade.php như mình chẳng hạn.
-