PHP
Laravel
Socialite
laravel5.6

【Laravel】Laravel5.6をソーシャルログインに完全対応する【Socialite】

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/を認証から除外する記述をしています。

この記述がないとユーザーがログアウトできなくなってしまいます。

以上です。