Webシステムへのユーザー登録は現状メールアドレスとパスワードによる認証が主流ですが、
メールの確認や登録フォーム入力の手間、パスワード紛失のリスクなどがありユーザーにとっても開発者にとっても面倒です。
TwitterやGoogleなどの既存アカウントによるソーシャルログインは、上記のような手間を解決しスムーズな登録が行えます。
また、初期値としてユーザー名やアイコン画像などの情報をシステム側へ自動インポート可能です。
今回は特にメジャーなTwitterとGoogleアカウントによるソーシャルログインをLaravelで実装します。
環境
- CentOS7
- PHP7.2
- MySQL5.6
- Laravel5.6
準備
- TwitterとGoogleの各APIキーを取得します。
- Twitterは最近開発ユーザーが承認制になったようで、利用目的などの軽い審査があります。
- Googleの方はウェブアプリケーション向けのプロジェクトを作成し、Google+のAPIを有効にします。
Authパッケージの追加
$ php artisan make:auth
Socialiteのインストール
$ composer require laravel/socialite
設定ファイルの編集
laravel/config/app.php
'providers' => [
…
Laravel\Socialite\SocialiteServiceProvider::class,
],
…
'aliases' => [
…
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
],
laravel/config/services.php
'twitter' => [
'client_id' => env('TWITTER_KEY'),
'client_secret' => env('TWITTER_SECRET'),
'redirect' => env('TWITTER_CALLBACKURL'),
],
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect' => env('GOOGLE_CALLBACKURL'),
],
laravel/.env
TWITTER_KEY="CONSUMER KEY"
TWITTER_SECRET="CONSUMER KEY(Secret)"
TWITTER_CALLBACKURL="CALLBACK URL"
GOOGLE_CLIENT_ID="CLient ID"
GOOGLE_CLIENT_SECRET="CLIENT ID(Secret)"
GOOGLE_CALLBACKURL="CALLBACK URL"
マイグレーション
- デフォルトのUserテーブルはメール認証向けのためソーシャルログイン向けに編集します。
- パスワード関連のテーブルは不要なためマイグレーションファイルごと削除します。
laravel/database/migrations/XXXX_create_users_table.php
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('status')->default(0);
$table->string('avatar');
$table->string('login_type');
$table->string('login_id')->unique();
$table->rememberToken();
$table->timestamps();
});
}
$ php artisan migrate
モデル
- インターフェイス「Illuminate\Contracts\Auth\Authenticatableを」をUserモデルに実装します。
- Userモデルだけはappディレクトリ直下に置くのが無難です。(Authパッケージで想定されているため)
laravel/app/User.php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\Authenticatable as IAuthenticatable;
use Illuminate\Auth\Authenticatable;
class User extends Model implements IAuthenticatable
{
use Authenticatable, Notifiable;
protected $fillable = [
'name', 'status', 'bio', 'avatar', 'login_type', 'login_id',
];
protected $hidden = [
'password', 'remember_token',
];
}
コントローラ
- パスワードと登録関連のコントローラは不要なので削除します。
- Loginコントローラを編集します。
- findOrCreate()では、DBを検索して存在すれば更新、なければ登録という処理を行っています。
laravel/app/Http/Controllers/Auth/LoginController.php
public function __construct()
{
$this->middleware('guest')->except(['logout', 'postLogout']);
}
public function index()
{
\Auth::logout();
return redirect()->to('/');
}
// ログアウト
public function postLogout()
{
\Auth::logout();
return redirect()->to('/');
}
// Google認証ページを表示
public function getGoogleRedirect()
{
return Socialite::driver('google')->redirect();
}
// Twitter認証ページを表示
public function getTwitterRedirect()
{
return Socialite::driver('twitter')->redirect();
}
// Googleのコールバック
public function getGoogleCallback()
{
try{
$login_info = Socialite::driver('google')->stateless()->user();
}catch(Exception $ex){
return redirect('login/google');
}
$auth_user = $this->findOrCreate("GP", $login_info);
\Auth::login($auth_user, true);
return redirect()->to('/home');
}
// Twitterのコールバック
public function getTwitterCallback()
{
try{
$login_info = Socialite::driver('twitter')->user();
}catch(Exception $ex){
return redirect('login/twitter');
}
$auth_user = $this->findOrCreate("TW", $login_info);
\Auth::login($auth_user, true);
return redirect()->to('/home');
}
// ユーザー情報を返す。存在しない場合は新規登録
protected function findOrCreate(string $login_type, $user_info)
{
$user = User::where('login_type', $login_type)->where('login_id', "$login_type{$user_info->id}")->first();
if(! $user){
// 存在しなければ新規登録
$user = new User();
$user->name = $user_info->name;
$user->status = 1;
$user->login_type = $login_type;
$user->login_id = "$login_type{$user_info->id}";
$user->avatar = $user_info->avatar_original;
$user->save();
}else{
// ユーザー情報更新
$user->name = $user_info->name;
$user->avatar = $user_info->avatar_original;
$user->save();
}
return $user;
}
ビュー
- こちらもパスワードや登録関連のファイルは不要なので削除します。
ルーティング
laravel/routes/web.php
Route::get('/', function () {
return view('welcome');
})->name('login');
Route::get('login/google', 'Auth\LoginController@getGoogleRedirect');
Route::get('login/google/redirect', 'Auth\LoginController@getGoogleRedirect');
Route::get('login/google/callback', 'Auth\LoginController@getGoogleCallback');
Route::get('login/twitter', 'Auth\LoginController@getTwitterRedirect');
Route::get('login/twitter/redirect', 'Auth\LoginController@getTwitterRedirect');
Route::get('login/twitter/callback', 'Auth\LoginController@getTwitterCallback');
Route::post('login/logout', 'Auth\LoginController@postLogout')->name('logout');
Route::get('/home', 'HomeController@index')->name('home');
まとめ
気を付ける点としては、GoogleのコールバックURLは登録したものと.envに記述するものを一致させる必要があります。
また、Loginコントローラのコンストラクタでlogin/logout/を認証から除外する記述をしています。
この記述がないとユーザーがログアウトできなくなってしまいます。
以上です。