Laravel Socialiteでソーシャルログインを実装してみた

LaravelはLaravel Socialiteを使って簡単にソーシャルログインを実装することができます。

Facebook、Twitter、LinkedIn、Google、GitHub、Bitbucketの認証をサポートすることが可能になります。

今回はLaravel Socialiteを使ってソーシャルログインを実装する方法について解説していきます。

githubはこちら
https://github.com/kmtitmk-ux/laravel-socialite

ソーシャルログインの要件

ソーシャルログインはIDやパスワードを入力してログインするのではなく、登録されたSNSアカウントにログインできるなら、こっちらにもログインできていることにしてしまうという仕組みです。

ソーシャルログインの要件はこちら。

  • 利用するソーシャルメディアはgoogle、facebook、twitterの3つ
  • SNSのidを利用して重複登録はされないようにする
  • SNSのidがデータベースに保存されている場合はそのままログインし、存在しない場合は新規ユーザー登録してログインさせる
  • ログインしているユーザーは連携するソーシャルメディアを追加できる

認証機能の作成

laravelをインストールしたら認証機能を作成します。

$ php artisan make:auth

データベースの作成

ユーザーのマイグレーションファイルを修正する。

カラムを追加し、null許可、ユニークに設定にする。

  • google_id
  • facebook_id
  • twitter_id

パスワードとメールアドレスをnull許可に変更。

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->string('email')->unique()->nullable();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password')->nullable();
        $table->string('twitter_id')->unique()->nullable();
        $table->string('google_id')->unique()->nullable();
        $table->string('facebook_id')->unique()->nullable();
        $table->rememberToken();
        $table->timestamps();
    });
}

マイグレーションファイルを修正したら、テーブルを作成。

$ php artisan migrate

モデルの修正

カラムを追加したので、モデルのUser.phpにも追記して保存できるようにする。

protected $fillable = [
    'name', 'email', 'password', 'google_id', 'facebook_id', 'twiiter_id'
];

Laravel Socialiteのインストール

composerでインストールします。

$ composer require laravel/socialite

config/services.phpに追記。

'twitter' => [
    'client_id' => env('TWITTER_CLIENT_ID'),
    'client_secret' => env('TWITTER_CLIENT_SECRET'),
    'redirect' => env('TWITTER_CLIENT_CALLBACK')
],

'google' => [
    'client_id' => env('GOOGLE_CLIENT_ID'),
    'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    'redirect' => env('GOOGLE_CLIENT_CALLBACK')
],

'facebook' => [
    'client_id' => env('FACEBOOK_CLIENT_ID'),
    'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
    'redirect' => env('FACEBOOK_CLIENT_CALLBACK')
],

.envファイルの修正。

各種SNSのクライアントID、シークレットID、コールバックURLを設定します。

クライアントIDとシークレットIDは、各種SNSのアカウントの方で作成して取得します。

コールバックURLもSNSの方で設定してください。

TWITTER_CLIENT_ID=クライアントID
TWITTER_CLIENT_SECRET=シークレットID
TWITTER_CLIENT_CALLBACK=/login/twitter/callback

GOOGLE_CLIENT_ID=クライアントID
GOOGLE_CLIENT_SECRET=シークレットID
GOOGLE_CLIENT_CALLBACK=/login/google/callback

FACEBOOK_CLIENT_ID=クライアントID
FACEBOOK_CLIENT_SECRET=シークレットID
FACEBOOK_CLIENT_CALLBACK=/login/facebook/callback

ログイン用のリダイレクト設定

routes/web.phpでログインURLを設定します。

Route::get('/login/{provider}', 'Auth\LoginController@redirectToProvider');

指定のURLにアクセスしたらredirectToProviderのコントローラーに通して、SNSの認証ページにリダイレクトさせます。

app/Http/Controllers/Auth/LoginController.phpに追記します。

public function redirectToProvider($provider)
{
    return Socialite::driver($provider)->redirect();
}

http://examole.com/login/googleのようにアクセスするとSNS認証用のURLにリダイレクトされます。

コールバックURLで保存とログイン処理の追加

routes/web.phpでコールバックURLを設定します。

Route::get('/login/{provider}/callback', 'Auth\LoginController@handleProviderCallback');

handleProviderCallbackのコントローラーを指定します。

SocialiteとUserのテーブルを取得するために、use App\User;とuse Socialite;を宣言します。

ユーザーテーブルへの保存処理とログイン処理を記述します。

public function handleProviderCallback($provider)
{
    try {
        $data = Socialite::driver($provider)->user();
    } catch (\Exception $e) {
        return redirect('/login');
    }

    $u = User::firstOrCreate([$provider.'_id' => $data->getId()], [
        $provider.'_id' => $data->getId(),
        'name' => $data->getName()
    ]);
    \Auth::login($u);

    return redirect($this->redirectTo);
}

firstOrCreateを使うと、各種SNSのidが存在しない場合は新規ユーザーを追加し、返却されたインスタンスを利用してログインさせます。

ログイン済みの場合

コンストラクターにログインしているかどうかの値を取得し、ログインしてない場合はユーザーIDをfalseにしておきます。

public function handleProviderCallback($provider)
{
    try {
        $data = Socialite::driver($provider)->user();
    } catch (\Exception $e) {
        return redirect('/login');
    }

    //追加か更新
    if ($this->user->id) {
        $u = User::where('id', $this->user->id)->update(
            [$provider.'_id' => $data->getId()]
        );
    } else {
        $u = User::firstOrCreate([$provider.'_id' => $data->getId()], [
            $provider.'_id' => $data->getId(),
            'name' => $data->getName()
        ]);
        \Auth::login($u);
    }

    return redirect($this->redirectTo);
}

ログインしているユーザーのIDを判別して、保存処理を変更します。

githubはこちら
https://github.com/kmtitmk-ux/laravel-socialite

正社員という奴隷制度に中指を立てるWebエンジニアです。PHPが得意。繋がれた鎖を断ち切るために、自由を取り戻すために、会社から独立するために、プログラミングスキルを磨く日々です。プログラミングと個人でもできるビジネスについて、情報発信しています。

詳しくはこちら