LaravelでFacebookログインを実装する

![laravel-v8.8.0](https://img.shields.io/badge/Laravel-v8.8.0-default) ![socialite-v5.0.1](https://img.shields.io/badge/socialite-v5.0.1-default)


# これはなに？

Facebookによるログインを実装する方法について、Laravelのインストールから解説します。
テストやエラーハンドリングについては書きません。

# 1 Laravelをインストールする
公式ドキュメントにしたがって進めます。
https://readouble.com/laravel/7.x/ja/installation.html

## Laravelプロジェクトを作成する

```
composer global require laravel/installer
```
```
laravel new fb_login
```


## ユーザ・認証をセットアップする

公式ドキュメントにしたがって進めます。
https://readouble.com/laravel/7.x/ja/authentication.html

パッケージ追加

```bash
composer require laravel/ui   
```

認証用の機能をセットアップする

```bash
 php artisan ui vue --auth 
```
色々細かい設定を聞かれますが、全部YESでOKです。

#### npmパッケージのインストールと、下準備を行う（多分SCSSとJSのビルド）
```
npm install && npm run dev
```

#### DBのマイグレーションを行う
```
php artisan migrate
```

## 開発用ローカルサーバーを起動する

```bash
> php artisan serve  
Starting Laravel development server: http://127.0.0.1:8000
```

起動時に表示されたURLにアクセスすると、ローカルサーバーに接続できます。

```
http://127.0.0.1:8000
```

ここまでうまく言っていると、以下のような画面が表示されるはずです。
![スクリーンショット 2020-10-05 11.05.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/998d5896-71ef-ae3f-a77d-94b2adeeed1a.png)

認証機能を追加しているので、左上に`Login` `Register`という表示があります。

Registerページ　`/register`
![スクリーンショット 2020-10-05 11.05.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/69bfefb9-8aa7-dfa0-1c15-7710d6c8e547.png)

ログイン後ページ `/home`
![スクリーンショット 2020-10-05 11.06.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/ae98c49c-85dc-6e4b-2928-653a695239f5.png)

`You are logged in!` と表示されてる通り、ログイン済みユーザーのみがこちらのページにアクセスできます。

# 2. SocialiteによるFacebook連携を実装する

## Socialiteをインストールする

SocialiteはLaravelでOAuthを簡単に実装できる便利なパッケージです。

```bash
composer require laravel/socialite    
```

## Facebookアプリを作成する

![スクリーンショット 2020-10-05 11.28.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/7d4bb053-e58b-48e3-d1da-b7767353b313.png)

- https://developers.facebook.com/ にアクセスし、新しいアプリを追加する
- `プロダクト`にFacebookログインを追加する


## Configに追加する

`config/services.php`

```

    'facebook' => [
        'client_id' => env('FACEBOOK_APP_ID'),
        'client_secret' => env('FACEBOOK_APP_SECRET'),
        'redirect' => env('FACEBOOK_CALLBACK_URL'),
    ],
```

## routeに追加する

```routes/web.php
Route::get('login/facebook', [LoginController::class, 'redirectToProvider']);
Route::get('login/facebook/callback', [LoginController::class, 'handleProviderCallback']);
```

```bash
php artisan route:list
```

![スクリーンショット 2020-10-05 11.46.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/9d4339b1-a4ec-116e-808b-49162da656c2.png)


## .envに設定追加
```.env
FACEBOOK_APP_ID=XXXXX
FACEBOOK_APP_SECRET=XXXXXXXXXXXXXXXXXXXXXX
FACEBOOK_CALLBACK_URL=http://localhost:8000/login/facebook/callback
```

- Facebookアプリのページを開き,`設定 > ベーシック` から `アプリID` と `app secret` をコピペします
- FACEBOOK_CALLBACK_URLにはweb.phpで設定したコールバック用のURLを設定します


## Controllerにメソッドを追加
2つのメソッドを追加します。
- redirectToProvider() : ログインボタンを押された時に、Facebook側ページにリダイレクトするためのエンドポイント
- handleProviderCallback() : Facebook側ページからリダイレクトを受けるエンドポイント

```\App\Http\Controllers\Auth\LoginController.php

    public function redirectToProvider()
    {
        return Socialite::driver('facebook')->redirect();
    }

    /**
     * Obtain the user information from GitHub.
     *
     * @return \Illuminate\Http\Response
     */
    public function handleProviderCallback()
    {
        $user = Socialite::driver('facebook')->user();

        dd($user); // Facebookから取得した情報を表示
    }
```

## 動作確認(Facebookとの連携)

ここまでうまくいくとFacebookとの連携ができるようになり、Facebookユーザーの情報を取得できるようになります。

- `http://localhost:8000/login/facebook`にアクセスする
- Facebook認証画面に遷移する
- ユーザー情報がブラウザに表示される（dd()コマンド)

![スクリーンショット 2020-10-05 11.55.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/dacd2740-cabf-166b-dc79-84c0af57065b.png)

続いて、ログイン機能を作っていきます。

# 3. ログイン機能を実装する

## FacebookIDとユーザーを紐づけるためのカラムを追加する

- usersテーブルにfacebook_idというカラムを追加します。
- アクセストークンを保存すれば、アクセストークンが有効な間はFacebookから情報を取得できます。
  - 今回は、ログイン時のみユーザー情報を取得できれば良いのでアクセストークンは保存しません。
- Facebookログイン時はパスワードが不要なので、NULLABLEに変更します。
- カラムの変更にはdoctrine/dbalが必要なのでインストールします。

```bash
 composer require doctrine/dbal  
```

マイグレーションファイルを追加します。

```bash
php artisan make:migration add_facebook_id_to_users   
```

作成されたファイルを編集します。

```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddFacebookIdToUsers extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('facebook_id')->nullable()->unique();
            $table->string('password')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('facebook_id');
            $table->string('password')->nullable(false)->change();
        });
    }
}

```

## ログインコントローラを編集し、FBによる登録とログインを実装する

handleProviderCallback（）を編集します。

```LoginController.php
    public function handleProviderCallback()
    {
        $user = Socialite::driver('facebook')->user();

        // すでにFacebook登録済みじゃなかったらユーザーを登録する
        $userModel = User::where('facebook_id', $user->id)->first();
        if (!$userModel) {
            $userModel = new User([
                'name' => $user->name,
                'email' => $user->email,
                'facebook_id' => $user->id
            ]);

            $userModel->save();
        }
        // ログインする
        Auth::login($userModel);
        // /homeにリダイレクト
        return Redirect::route('home');
    }
```

## Userモデルを編集し、FacebookIDも保存できるようにする
```Users.php

    protected $fillable = [
        'name',
        'email',
        'password',
        'facebook_id',
    ];
```
fillableにfacebook_idを追加します。
これをしないとUserモデルのsave()を実行しても、facebook_idが保存されません。

## login.bladeにログインボタンを追加する

login.bladeを開き,適当な場所に以下のHTMLを追加します。

```html
<a href="/login/facebook">Facebookでログイン</a>
```

## 動作確認（Facebookログイン）

ログイン画面`/login` を表示し、「Facebookでログイン」をクリックします。
![スクリーンショット 2020-10-05 12.20.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/6e3eccb3-5330-ea96-e7cb-29d53d3f095f.png)

Facebookの認証画面に遷移します。
![スクリーンショット 2020-10-05 12.20.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/30f3c3d3-cf5b-dfde-ca83-f2da6b065058.png)

Facebook側で「XXとしてログイン」をクリックするとマイページに遷移し、Facebookに登録している情報でログインされます。
![スクリーンショット 2020-10-05 12.20.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/82f2c584-d3e1-e4e8-ea4e-ae9a24594662.png)

一度ログアウトして、再度ログインページから「Facebookでログイン」を押してもログインできます。

Facebookログインが実装できました🎊

## 終わり

Facebookによるログインを実装する方法をざっくりと書きました。
Laravelはインストールから認証の実装までがコマンドですぐにできてとても便利です。
Facebook連携にはSocialiteを使うことでこちらも簡単に実装できました。

以上、参考になりましたら幸いです。