今回は、LaravelでSocialiteを使って、GoogleとFacebookのSNSアカウントを利用したソーシャルログイン認証について説明します。
なぜこの2つかと言うと、複数のSNSを使った場合の効率の良い導入方法の紹介と、単純に有名なSNSかつメールアドレスを取得できること。
Socialiteでソーシャルログイン認証
Twitterのようにメールアドレスが取得できないと後々不便になるから導入しません。(経験則です)
あと、SNSからはログイン認証に必要な最低限のデータのみ取得することにします。
基本的に少しコードを追加するだけなので、電話番号とかアバターなどを取得したい方は別途調べてください。
事前準備(SNSの設定)
LaravelのSocialiteパッケージでソーシャルログイン認証をするには、まずは各SNSの開発者(Developers)画面から、クライアントID(アプリID)やシークレットIDを取得し、コールバックURLの設定を行ってください。
そしてそれらの情報を設定ファイルに入力しておきましょう。
以下の3つの情報をSNS毎に設定ファイルに記載します。
- client_id・・・クライアントID
- client_secret・・・シークレットID
- redirect・・・コールバックURL(認証後に遷移するページ)
/config/services.php
ここでは、必要な情報を格納する変数を設定します。
実際の設定値は、次の設定ファイル(.env)に記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * socialite Settings */ 'facebook' => [ 'client_id' => env('FACEBOOK_API_ID'), 'client_secret' => env('FACEBOOK_API_SECRET'), 'redirect' => env('FACEBOOK_CALLBACKURL'), ], 'google' => [ 'client_id' => env('GOOGLEPLUS_API_ID'), 'client_secret' => env('GOOGLEPLUS_API_SECRET'), 'redirect' => env('GOOGLEPLUS_CALLBACKURL'), ], |
.env
実際の値は[.env]ファイルに記載します。
1 2 3 4 5 |
FACEBOOK_API_ID=XXXXXXXXXXXXXXXX FACEBOOK_API_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX FACEBOOK_CALLBACKURL=https://[your domain]/login/facebook/callbackGOOGLEPLUS_API_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com GOOGLEPLUS_API_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXX GOOGLEPLUS_CALLBACKURL=https://[your domain]/login/google/callback |
Socialiteパッケージのインストール
LaravelのGitHubにも入っているパッケージ「Socialite」をインストールしてソーシャルログイン認証を行います。
まずは、いつも通り[composer require]します。
1 |
composer require laravel/socialite |
Socialiteを有効にする
次に、設定ファイルのprovidersとaliasesに[Socialite]追記します。
/config/app.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
'providers' => [ ... /* * Package Service Providers... */ Laravel\Socialite\SocialiteServiceProvider::class, ], 'aliases' => [ ... /* * Packages aliases... */ 'Socialite' => Laravel\Socialite\Facades\Socialite::class, ], |
これでSocialiteの準備は完了です。
SNSアカウント用のテーブル作成
SNSアカウントでログインする場合は、パスワード(場合によってはメールアドレス)が不要になるので、既存のUsersテーブルを変更しなければなりません。
変更するためにはDoctrineのdbal(Database Abstraction Layer)なるものが必要らしいです。(ココちょっとハマった)
これも[composer require]します。
1 |
composer require doctrine/dbal |
次に、Usersテーブルを変更するためのLaravel標準のマイグレーションファイルを作成し、
1 |
php artisan make:migration update_users_table --table users |
以下のように書きます。
/database/migrations/…_update_users_table.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class UpdateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('users', function (Blueprint $table) { // $table->string('email')->nullable()->change(); $table->string('password')->nullable()->change(); }); } /** * Reverse the migrations. * * @return void */ public function down() { // } } |
ここまででUsersテーブルを変更する準備が完了しました。
次は、Usersテーブルと紐付くSNSアカウントの情報を登録するテーブルとモデルを作成していきます。
ここもコマンドでパパっと!
1 |
php artisan make:model SocialAccount --migration |
モデルと一緒にマイグレーションファイルも以下のように作成します。
/database/migrations/…_create_social_accounts_table.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateSocialAccountsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('social_accounts', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->nullable(); $table->string('provider'); $table->string('provider_id'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('social_accounts'); } } |
/app/SocialAccount.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; class SocialAccount extends Model { protected $table = 'social_accounts'; protected $primaryKey = 'id'; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'user_id', 'provider_id', 'provider', ]; public function user() { return $this->belongsTo('AppUser'); } } |
これでソーシャルログイン認証の準備が整いました。
ソーシャルログイン認証処理を追記
通常のログインコントローラーにソーシャルログイン認証処理を付け加えます。
/app/Http/Controllers/LoginController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/** * redirect to oauth page * * @return IlluminateHttpResponse */ public function redirectToProvider($provider) { return Socialite::driver($provider)->redirect(); } /** * get user info from oauth * * @return IlluminateHttpResponse */ public function handleProviderCallback($provider) { try { $user = Socialite::driver($provider)->user(); $account = SocialAccount::firstOrCreate([ 'provider' => $provider, 'provider_id' => $user->getId(), ]); if (empty($account->user)) { $user = User::create([ 'name' => $user->getName(), 'email' => $user->getEmail() ]); $account->user()->associate($user); } $account->save(); Auth::login($account->user, true); } catch (Exception $e) { return redirect('/login'); } return redirect($this->redirectTo); } |
[redirectToProvider($provider)]で各SNSのログイン認証画面へリダイレクトさせ、[handleProviderCallback($provider)]で帰ってきた値を利用して登録orログインを行います。
/routes/web.php
最後にルートを追加して完了です。
1 2 |
Route::get('login/{provider}', 'AuthLoginController@redirectToProvider'); Route::get('login/{provider}/callback', 'AuthLoginController@handleProviderCallback'); |
{provider}に”google“や”facebook“が入ります。リンクはこんな感じ。
1 2 |
<a href="{{ url('login/facebook') }}" class="btn btn-primary"><i class="fa fa-facebook"></i> Facebook でログインする</a> <a href="{{ url('login/google') }}" class="btn btn-danger"><i class="fa fa-google-plus"></i> Google+ でログインする</a> |
コメント