スクリーンショット_2020-01-22_18

Laravel6.0+SocialiteでTwitterログインを実装する

こんにちは。
大阪でフリーのエンジニア&プログラミング講師をやっている向江です。

最近ECサイトを作るチュートリアル書いてるんで
こっちもあとで見てね。

https://note.com/mukae9/n/n12cc13fd4f90

今回はLaravelでTwitterログインを実装する方法を書いてみたいと思います!

Laravelの環境構築については

Macの方
https://qiita.com/mukae_tech/items/24709085948a6d707da3

Windowsの方
https://qiita.com/mukae_tech/items/89075e7caf7d6506e0b3

で詳しくまとめていますのでご参考下さい。

また、そもそもTwitterログインを実装するためには
Twitter Apiを使用する許可が必要となるため、そちらから初めてください!
許可を取るための情報はこの記事にまとめていますので参考にしてください!(許可が出るのが次の日とかになります)

https://note.com/mukae9/n/nb249bcfe6ee9

1、とりあえず認証機能を追加

Laravelには強力な認証機能の自動構築が可能です。

この記事の前半でまとめてますのでまずは下記の画像のようにWelcome画面がなるようにしてみてください!

https://note.com/mukae9/n/n12cc13fd4f90

スクリーンショット 2020-01-17 14.55.23

右上にログインとレジスターが追加されましたね!

2、Socialiteをcomposerでダウンロード。


それでは早速composerを利用してsocialite機能に必要なやつファイルを一気に取得します。

コマンドをうつ場所はLaravel自体のフォルダです。
app/routes/publicなどが直下にあるフォルダです。

composer require laravel/socialite

これでOK!

するとSNSログインに必要なファイルが準備されます。
初心者がその構成の全てを見ると闇落ちしますので、
必要部分だけの説明に留めておきます。

いつか自分がLaravelのことを理解し始めた時に改めてvenderフォルダに潜むそれらの機能のファイル群と向き合ってみてください。

今はLaravel開発者たちに感謝を述べるくらいでいいかと。

3、とりあえずルーティング


routes/web.phpにTwitterのためのルーティングを書きます。

Route::get('login/twitter', 'Auth\LoginController@redirectToTwitterProvider');
Route::get('login/twitter/callback', 'Auth\LoginController@handleTwitterProviderCallback');

login/twitterの方にアクセスするとTwitter経由での認証処理が始まります。
login/twitter/callbackはTwitterのアプリ側から情報が帰ってくるURLです。

※もしTwitter以外でもログインを実装するなら
Route::get('login/{provider}/callback', 'Auth\LoginController@handleProviderCallback');
とかにして{provider}部分で値を持たせてtwitterとかgithubなどに切り替えると良いですが今回はわかりやすく行きます。

流れを単純化すると、

①login/twitterのURLをユーザーが踏む

②Twitterアプリ側が認証をする
認証が成功したら

③login/twitter/callbackへユーザー情報を返すので
それをUserテーブルに保管する

という流れになっています。

それでは、ルーティングはできたので肝心なControllerへの処理を書いていきます。


3、コントローラーに処理を記述する①

上記の章でlogin/twitterにアクセスされた場合は、
Auth\LoginController@redirectToTwitterProviderの処理を行うようになっています。

このLoginControllerは1、の章で自動で生成されています。
app/http/Controllers/Authにありますね。

ここにまずはredirectToTwitterProviderメソッドを作ってしまいます。

    public function redirectToTwitterProvider()
   {
       return Socialite::driver('twitter')->redirect();
   }

これだけでTwitterアプリ側に認証を求めに行くことになりますが、
もちろん何にも設定をしていないので、今はエラーが出ます。

Socialite::driver('twitter')がガッツリと機能してこのTwitterログインを可能としていますが、うまく機能させるための記述をしていく必要があります。

4、使う前の下準備



まずは
Socialite::を使うために
サービスプロバイダへの登録とエイリアスの作成を行います。

config/app.phpを開いてみましょう。
まずはここの

'providers' => []に以下を記述します。

    'providers' => [

       /*
        * Laravel Framework Service Providers...
        */
       Illuminate\Auth\AuthServiceProvider::class,
       Illuminate\Broadcasting\BroadcastServiceProvider::class,
          
            〜省略〜    

       App\Providers\RouteServiceProvider::class,

       //これ追加!!
       Laravel\Socialite\SocialiteServiceProvider::class,

   ],

次に


    'aliases' => [

       'App' => Illuminate\Support\Facades\App::class,
       'Arr' => Illuminate\Support\Arr::class,
       'Artisan' => Illuminate\Support\Facades\Artisan::class,
       'Auth' => Illuminate\Support\Facades\Auth::class,
       'Blade' => Illuminate\Support\Facades\Blade::class,
       'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
             
                    
                    〜省略〜
        
 
       'Str' => Illuminate\Support\Str::class,
       'URL' => Illuminate\Support\Facades\URL::class,
       'Validator' => Illuminate\Support\Facades\Validator::class,
       'View' => Illuminate\Support\Facades\View::class,

     //これを追加!
       'Socialite' => Laravel\Socialite\Facades\Socialite::class,
       

   ],

];

これで下準備が出来ました。
しかしまだ足りません。

Twitterアプリに認証部分を委託するためには
そのTwitterアプリの情報を伝える必要があります。

そういった情報を記述するための
config/services.phpに以下を記述します。
(ちなみにここを見に行ったりすする処理が
vender/laravel/socialite/SocialiteManager.phpに書かれています。)

'twitter' => [
       'client_id' => env('TWITTER_CLIENT_ID'),
       'client_secret' => env('TWITTER_CLIENT_SECRET'),
       'redirect' => env('CALLBACK_URL')
],

直接ここにidとかを書いてもいいのですが、
laravelフォルダ直下にある.envから拾うようにしています。

.envに以下を追記します。

TWITTER_CLIENT_ID=************************* //下を参照
TWITTER_CLIENT_SECRET=************************* //下を参照
CALLBACK_URL=http://localhost/login/twitter/callback //よく見たらルーティングしたやつ

TWITTER_CLIENT_ID
TWITTER_CLIENT_SECRET
はやっとTwitterApiの申請の許可をもらった部分がいきてきます!

https://developer.twitter.com/en/apps
で「create app」をクリック

スクリーンショット 2020-01-22 13.24.30

こんな画面になるので、
よしなに記入をしていきます。

肝心なところは、

Allow this application to be used to sign in with TwitterLearn more
■Enable Sign in with Twitter
にチェックを入れて、

Callback URLs (required)
には先ほど.envにも記述した

http://localhost/login/twitter/callback

を記述。

あとは項目をGoogle翻訳に頼みながら完了させます。

スクリーンショット 2020-01-22 15.38.45

また上記のようにpermissionsで
Additional premissionsにチェックが入っていないとEmail情報が取得できないので許可を出しておきます。

そして作成されたappをクリックするとこの画面にいけますので、
下の画像のように
左上の青文字らへん「Keys and tokens」にタブをきり変えてください。
この画面になりましたか?

スクリーンショット 2020-01-22 13.28.40

見え難いですが、
API Key が TWITTER_CLIENT_ID
API secret key が TWITTER_CLIENT_SECRET
ということになります。

.envにそのままコピペしましょう!

さあこれで下準備も終わりました!

ただ、
http://localhost/login/twitterにアクセスにしても
Twitterにログインを求める画面までは行けても

Route::get('login/twitter/callback', 'Auth\LoginController@handleTwitterProviderCallback');

の方のメソッドで何もしていないので
エラーになってしまいます。

先にそちらの記述をします。


3、コントローラーに処理を記述する②

Auth\LoginControllerに
handleTwitterProviderCallbackを実装します。

    public function handleTwitterProviderCallback(){

       try {
           $user = Socialite::with("twitter")->user();
       } 
       catch (\Exception $e) {
           return redirect('/login')->with('oauth_error', 'ログインに失敗しました');
           // エラーならログイン画面へ転送
       }
       
       $myinfo = User::firstOrCreate(['token' => $user->token ],
                 ['name' => $user->nickname,'email' => $user->getEmail()]);
                 Auth::login($myinfo);
                 return redirect()->to('/'); // homeへ転送
    
    }

まずは
try{
       $user = Socialite::with("twitter")->user();
}
でTwitterアプリ側から帰ってきた情報を取得します。
ここでエラーがあった場合(認証に失敗した場合)などはloginページにリダイレクトするようにしています。

もうこれでTwitterアプリでの認証が終わり、そのログインしようとしている方の情報を取得できているので実質ほぼ完了しています!

あとはuserテーブルにその人の情報を投げ込んで行くだけですが一工夫。

$myinfo = User::firstOrCreate(['token' => $user->token ],
          ['name' => $user->nickname,'email' => $user->getEmail()]);
          Auth::login($myinfo);
          return redirect()->to('/'); // ホームへ転送

$myinfo = User::firstOrCreate(['token' => $user->token ],['name' => $user->nickname,'email' => $user->getEmail()]);


firstOrCreateはよく使うやつですね。
第一引数で['token' => $user->token ]を指定することでusersテーブルのtokenカラムに同じ値を持つレコードがあるかチェックしてくれます。

※emailで判断するとTwitter側でユーザーがメールアドレスを変えた時に対応出来ない!

その後、
レコードがある場合→$myinfoにそのレコードをオブジェクトで代入

レコードがない場合→第一・第二引数どちらもINSERTしてその情報を$myinfoにオブジェクトで代入

どちらに転んでも$myinfoにはオブジェクトで情報が入ることになります!

ただこのままでは、userテーブルの必須カラムであるpasswordがnullなのでINSERTに失敗しちゃいます!
またtwittertokenを保存するカラムも追加しておきます。

database/migrationフォルダにある
2014_10_12_000000_create_users_tableのupメソッドを変えておきます!

    public function up()
   {
       Schema::create('users', function (Blueprint $table) {
           $table->bigIncrements('id');
           $table->string('name');
           $table->string('email')->unique();
           $table->timestamp('email_verified_at')->nullable();
           $table->string('password')->nullable(); //->nullabale();追加
           $table->string('token')->nullable(); //追加
           $table->rememberToken();
           $table->timestamps();
       });
   }

※passwordのnullを許可するのは実務的にはなんともですが説明簡略化のためご了承を。

User.phpというappフォルダ直下のモデルを編集します。

    protected $fillable = [
       'name', 'email', 'password', 'token'
   ];

これでuserテーブルで変更できるカラムは
 'name', 'email', 'password',に加えて'token'も追加されることになりました!


後はこの設定でmigrateをしておきます!

usersテーブルを見てみると、入力された情報が確認できるかと思います。

ここまできたら後は、
Auth::login($myinfo);
でログインする処理をしてあげます!

これでメイン画面にリダイレクトされて完了!

右上が写真のようにHomeに変わってログイン状態であることが分かります!

スクリーンショット 2020-01-22 18.08.09


これでTwitterでのログイン機能の実装の基本はだいたいOKです!
他のGoogleログイン、Facebookログインもだいたい同じ使い方なので
結構簡単に実装できます。

ただ、パスワードの問題やtokenの許可時間、

またTwitterログインで取得出来る情報だけでは、通常の会員登録で得られる情報と差があるので別のフォームで埋める必要がある…!

とかそこらへんも実装してあげる必要があります!

ただそれでも、これだけの手間でSNSログインを実装できるsocialiteは魅力的ですね!

この記事が気に入ったらサポートをしてみませんか?