LoginSignup
58
49

More than 5 years have passed since last update.

Laravel 5.3で外部アカウントを使用した認証機能を実装する方法

Last updated at Posted at 2016-10-03
  • LaravelではfacebookやtwitterのOAuth認証によるログイン機能を実現するためのパッケージ「laravel/socialite」が存在する。
  • 日本国内向けのサービス(LINEやYahoo!JAPAN)を使った認証はサポートされていないが、これについてはこちらのポストで。

追記

  • 2017.05.19

SocialController::createOrGetUser()において、各種サービスから取得したメールアドレスを保存していたが、make:authを使って作成する認証方式を併用する場合に、SNS登録メールアドレスとバッティングしてログインできなくなる事象があったため、該当箇所をコメントアウトしました。

前提

導入手順

laravel/socialiteパッケージを取得

  • composer requireでパッケージを取得する。

    cd (/your/laravel/project/path)
    composer require laravel/socialite
    
  • config/app.phpを編集する

    config/app.php
    <?php
    
    return [
        ...
        'providers'       => [
            ...
            //laravel/socialite
            Laravel\Socialite\SocialiteServiceProvider::class,
            ...
        ],
        ...
        'aliases'         => [
            ...
            //laravel/socialite
            'Socialite'    => Laravel\Socialite\Facades\Socialite::class,
            ...
        ],
    
    ];
    
    

socialiteの設定

  • 各OAuthサービスごとに、ID,トークンや認証処理後のコールバックURLなどを指定する必要がある。

    • config/services.phpを編集する。

      config/services.php
      <?php
      
      return [
          ...
          //Socialite認証
          'twitter'   => [
              'client_id'     => env('TWITTER_CLIENT_ID'),
              'client_secret' => env('TWITTER_CLIENT_SECRET'),
              'redirect'      => env('TWITTER_REDIRECT'),
          ],
          'facebook'  => [
              'client_id'     => env('FACEBOOK_CLIENT_ID'),
              'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
              'redirect'      => env('FACEBOOK_REDIRECT'),
          ],
          'google'    => [
              'client_id'     => env('GOOGLE_CLIENT_ID'),
              'client_secret' => env('GOOGLE_CLIENT_SECRET'),
              'redirect'      => env('GOOGLE_REDIRECT'),
          ],
      ];
      
      
    • .env.xxxxxを編集

      env.xxxxx
      ...
      TWITTER_CLIENT_ID=(twitter-client-id)
      TWITTER_CLIENT_SECRET=(twitter-client-secret)
      TWITTER_REDIRECT=(twitter-redirect-url)
      
      FACEBOOK_CLIENT_ID=(facebook-client-id)
      FACEBOOK_CLIENT_SECRET=(facebook-client-secret)
      FACEBOOK_REDIRECT=(facebook-redirect-url)
      
      GOOGLE_CLIENT_ID=(google-client-id)
      GOOGLE_CLIENT_SECRET=(google-client-secret)
      GOOGLE_REDIRECT=(google-redirect-url)
      ...
      

テーブル&モデル作成

  • 認証に使用するテーブルを作成する

    • migration作成

      cd your/laravel/project/path
      php artisan make:migration create_social_accounts_table
      
      database/migrations/xxxx_xx_xx_xxxxxx_social_accounts.php
      <?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')->unsigned()->nullable();
                  $table->string('provider_user_id');
                  $table->mediumText('provider_access_token')->nullable();
                  $table->string('provider');
                  $table->timestamps();
                  $table->softDeletes();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::drop('social_accounts');
          }
      }
      
    • usersテーブルの定義修正

      database/migrations/2014_10_12_000000_create_users_table.php
      <?php
      
      // ...
      
      class CreateUsersTable extends Migration
      {
          // ...
      
              public function up()
          {
              Schema::create('users', function (Blueprint $table) {
                  // ...  
                  // $table->string('email')->unique();   // -    
                  // $table->string('password');          // -
                  $table->string('email')->nullable();    // +
                  $table->string('password')->nullable(); // +
                  // ...
              });
          }
      
          //...
      }
      
      • 認証に使用するサービスによって、取得できる項目は違うため、このへんのnullable対応は必要に応じて実施する。
    • テーブル作成

      cd your/laravel/project/path
      php artisan migrate:refresh
      
  • 認証に使用するテーブルのモデルを用意する。

    app/SocialAccount.php
    
    <?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_user_id',
            'provider_access_token',
            'provider',
        ];
    
        public function user()
        {
            return $this->belongsTo(User::class);
        }
    }
    
    

コントローラ作成

  • 認証に使用するコントローラを作成する

    app/Http/Controllers/Auth/SocialController.php
    <?php
    namespace App\Http\Controllers\Auth;
    
    use App\Http\Controllers\Controller;
    use Illuminate\Http\Request;
    use Auth;
    use Socialite;
    
    use App\User;
    use App\SocialAccount;
    
    class SocialController extends Controller
    {
        protected $redirectTo = '/home';        //your-redirect-url-after-login
    
        // twitter
    
        public function getTwitterAuth()
        {
            return Socialite::driver('twitter')->redirect();
        }
    
        public function getTwitterAuthCallback()
        {
            $twitterUser = Socialite::driver('twitter')->user();
    
            $user = $this->createOrGetUser($twitterUser, 'twitter');
            Auth::login($user, true);
    
            return redirect($this->redirectTo);
        }
    
        // facebook
    
        public function getFacebookAuth()
        {
            return Socialite::driver('facebook')->redirect();
        }
    
        public function getFacebookAuthCallback()
        {
            $facebookUser = Socialite::driver('facebook')->stateless()->user(); // (1)
    
            $user = $this->createOrGetUser($facebookUser, 'facebook');
            Auth::login($user, true);
    
            return redirect($this->redirectTo);
        }
    
        // Google
    
        public function getGoogleAuth()
        {
            return Socialite::driver('google')->redirect();
        }
    
        public function getGoogleAuthCallback()
        {
            $googleUser = Socialite::driver('google')->user();
    
            $user = $this->createOrGetUser($googleUser, 'google');
            Auth::login($user, true);
    
            return redirect($this->redirectTo);
        }
    
        public function createOrGetUser($providerUser, $provider)
        {
            $account = SocialAccount::firstOrCreate([
                'provider_user_id' => $providerUser->getId(),
                'provider'         => $provider,
            ]);
    
            if (empty($account->user))
            {
                $user = User::create([
                    'name'   => $providerUser->getName(),
                    // 'email'  => $providerUser->getEmail(), # 削除 (2017.05.19)
                    'avatar' => $providerUser->getAvatar(),
                ]);
                $account->user()->associate($user);
            }
    
            $account->provider_access_token = $providerUser->token;
            $account->save();
    
            return $account->user;
        }
    }
    

ルーティング設定

  • routes/web.phpに追加

    routes/web.php
    ...
    //twitter
    Route::get('/login/twitter', 'Auth\SocialController@getTwitterAuth');
    Route::get('/login/twitter/callback', 'Auth\SocialController@getTwitterAuthCallback');
    
    //facebook
    Route::get('/login/facebook', 'Auth\SocialController@getFacebookAuth');
    Route::get('/login/facebook/callback', 'Auth\SocialController@getFacebookAuthCallback');
    
    //google
    Route::get('/login/google', 'Auth\SocialController@getGoogleAuth');
    Route::get('/login/google/callback', 'Auth\SocialController@getGoogleAuthCallback');
    ...
    

導線作成

  • どこかしらのビューに、認証用URLへの導線を張る
any.view.blade.php
...
(例)
<div class="container">
    <div class="btn-group btn-group-justified">
        <a class="btn btn-default" href="/login/facebook">
            facebook
        </a>
        <a class="btn btn-default" href="/login/twitter">
            twitter
        </a>
        <a class="btn btn-default" href="/login/google">
            google
        </a>
    </div>
</div>
...
58
49
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
58
49