TwitterAPI+LaravelでTwitterログイン機能を実装する

# はじめに
今回は、アプリ開発している中でTwitterログイン機能を実装したのでTwitterログイン機能実装について書いていきます。

# 前提
- Twitter Developer登録済み + APIKey・API SecuretKey・callbackURL取得済み

[Twitter Developerのリンク](https://developer.twitter.com/)
上記のサイトで、TwitterAPIを取得する必要がある。
~~TwitterAPIをどういった目的で使うかなどを英語で200字以上で書くことが結構大変~~

# Socialiteをインストールと使用前の設定
Laravelでは、SocialiteというものでOAuthプロバイダによる認証方法を提供している。
>Socialiteは現在、Facebook、Twitter、LinkedIn、Google、GitHub、GitLab、Bitbucketによる認証をサポートしています。
[Laravel7公式ドキュメント](https://readouble.com/laravel/7.x/ja/socialite.html)より

インストールは簡単！以下のコマンドでOK

```
composer require laravel/socialite
```

インストール後は、`config/app.php`にprovidersとaliasの設定を行う。

```php:config/app.php

'providers' => [ 
    Laravel\Socialite\SocialiteServiceProvider::class,
],
'aliases' => [
    'Socialite' => Laravel\Socialite\Facades\Socialite::class,
]
```

次に、config/services.phpで設定を行う。
>Socialiteを使用する前に、アプリケーションで使用するOAuthサービスの認証情報も追加する必要があります。認証情報はconfig/services.php設定ファイルで指定し、アプリケーションの必要に合わせ、facebook、twitter、linkedin、google、github、gitlab、bitbucketキーを使用してください。
[Laravel7公式ドキュメント](https://readouble.com/laravel/7.x/ja/socialite.html)より

公式ドキュメント感謝。

今回は、Twitterを用いるので、下記の認証情報をconfig/service.phpに追加する。

```php:config/service.php

"twitter" => [
        "client_id" => env("TWITTER_API_KEY"),
        "client_secret" => env("TWITTER_API_SECRET"),
        "redirect" => env("TWITTER_CALLBACK"),
]
```

続いて、.envファイルにてTwitterAPI KeyとTwitterAPI SecretKeyとcallbackURLを指定する。
これらは、TwitterDeveloperより取得できる！

```php:.env
TWITTER_CLIENT_ID = TwitterAPIKey
TWITTER_CLIENT_SECRET = TwitterAPI SecretKey
CALLBACK_URL = callbackURL
```

# 実際に実装していく！
まずはルーティングの実装を行います。
web.phpにて、下記ルーティングを追加

```php:web.php
Route::get('/auth/twitter', 'Auth\TwitterController@redirectToProvider');
Route::get('/auth/twitter/callback', 'Auth\TwitterController@handleProviderCallback');
Route::get("/auth/twitter/logout","Auth\TwitterController@logout");
```

※このとき、２番目のルーティングで指定するURLは、TwitterDeveloperで設定したcallbackURLと同じであることに注意。

次に、実際にコントローラを作成していく。
全体図は以下の通り。

```php:TwitterController.php
class TwitterController extends Controller
{
    //Twitterの認証ページへユーザーをリダイレクト
    public function redirectToProvider()
    {
        return Socialite::driver('twitter')->redirect();
    }

    //ログイン
    public function handleProviderCallback()
    {
        try {
            //認証結果の受け取り
            $user = Socialite::driver('twitter')->user();
        } catch (Exception $e) {
            return redirect('/');
        }

        $authUser = $this->findOrCreateUser($user);
        Auth::login($authUser, true);

        return redirect()->route('home');
    }

    //Twitterユーザー情報をもとに、ユーザー情報を取得するか新たにユーザーを作成する
    public function findOrCreateUser($twitterUser)
    {
        $authUser = User::where('twitter_id', $twitterUser->id)->first();

        if ($authUser) {
            return $authUser;
        }

        //DBにユーザー情報がなければ作成する
        return User::create([
            'name' => $twitterUser->nickname,
            'twitter_id' => $twitterUser->id,
            'avatar' => $twitterUser->avatar_original,
        ]);
    }

    public function logout()
    {
        Auth::logout();

        return redirect('/');
    }
}
```


細かく説明していきます。
***〇redirectToProvierメソッド***

```php:TwitterController.php
public function redirectToProvider()
{
        return Socialite::driver('twitter')->redirect();
}
```
こちらは、Twitter認証ページへリダイレクトする処理を記載しています。

redirectメソッドによって、ユーザーをOAuthプロバイダへ送る。
このdriverメソッド内に、githubなどを指定するとほかの認証ページに遷移できる。

***〇findOrCreateUserメソッド***

```php:TwitterController.php
public function findOrCreateUser($twitterUser)
{
    $authUser = User::where('twitter_id', $twitterUser->id)->first();

    if ($authUser) {
        return $authUser;
    }

    //DBにユーザー情報がなければ作成する
    return User::create([
        'name' => $twitterUser->nickname,
        'twitter_id' => $twitterUser->id,
        'avatar' => $twitterUser->avatar_original,
    ]);
}
```

こちらでは、Twitterアカウントの情報をもとに、ユーザー情報を取得するか新しくアカウントを作成を行っている。

具体的には、Twitter_idがDB内にあれば、そのユーザー情報を返す。なければDBにアカウント情報を追加している。

***〇handleProviderCallbackメソッド***

```php:TwitterController.php
public function handleProviderCallback()
{
    try {
        //認証結果の受け取り
        $user = Socialite::driver('twitter')->user();
    } catch (Exception $e) {
        return redirect('/');
    }

    $authUser = $this->findOrCreateUser($user);
    Auth::login($authUser, true);

    return redirect()->route('home');
}
```
`Socialite::driver('twitter')->user();`でTwitterのアカウント情報を取得しています。
何らかのエラーが起きた場合は、トップページにリダイレクトします。

そして、取得したアカウント情報を先ほど説明したfindOrCreateUserメソッドに渡します。
ログイン処理を行い、ホームのページにリダイレクトします。

***〇logoutメソッド***

```php:TwitterController.php
public function logout()
{
    Auth::logout();

    return redirect('/');
}
```
こちらは特に解説する箇所もなく、ログアウト処理を行いトップページにリダイレクトしています。

# Twitterログインボタンの設置
こんな感じでログインボタンを設置

```php:login.blade.php
<button type="submit" class="btn twitter-btn">
    <a href="/auth/twitter"><i class="fab fa-twitter"></i> Twitter Login</a>
</button>
```

Twitterのカラーコード： #00aced 
こちらのカラーコードを使用すれば、Twitterログインボタンの完成！

# DB関連の設定
Laravelアプリケーションを作成した際に作られる、デフォルトのusersテーブルを使用する際、すこし手を加える必要があります。

というのも、もしTwitterアカウントでログインした場合、Twitterアカウントから取得するデータを入れるカラムを追加する必要があります。今回取得するデータはnickname（name）・id・avatarの３つ。これらのカラムを新たに追加します！

また、usersテーブルではemailやpasswordが必ず必要になっているためnullableに変更する。（Twitter認証でアカウント登録した場合、emailやpasswordのデータは取得しないため）

Laravelは、デフォルトではカラム変更のマイグレーションを行うことが出来ない。そのため新たにパッケージ（doctrine/dbal）をインストールする必要がある。

```
composer require doctrine/dbal
```
あとは、変更用のマイグレーションを作成して実行すればOK。

また、User.phpにてカラムの追加もする。

```php:User.php
protected $fillable = [
    'name', 'email', 'password', 'twitter_id', 'avatar',
];
```

# まとめ
今回は、TwitterAPIとLaravelを用いてTwitterログイン機能を実装しました。
今までは外部API？難しそう～。と思っていましたがやってみるとそんなに難しくなかったです。（というのも、ネットで調べれば様々なサイトに詳しく書いてあるから）

とても勉強になりました！
是非みなさんの参考になれば幸いです！