57
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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>
...
57
47
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
57
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?