LoginSignup
21
22

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-09-17

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/を認証から除外する記述をしています。
この記述がないとユーザーがログアウトできなくなってしまいます。

以上です。

21
22
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
22