Laravel / Socialite で気をつけるべき事のまとめ

現在の開発で Laravel/Socialite を使ったソーシャル・ログインを作っています。

このパッケージはとても便利で以下の手順を踏むだけでユーザー登録/ログインの手間を省くことができます。

1.Twitter や Facebook の特定ページヘリンクを貼る
2.アクセス許可の設定(すでに許可設定されていればここはスキップ)
3.指定したページヘリダイレクトしてくるので、そこでユーザー情報を登録 or 自動ログイン

ひとつひとつソーシャルログインを実装していた一昔のことを考えるとどれだけ開発が省略されたことかとホントに感心しますね。

さて、こんな便利な Laravel/Socialite ですが、ユーザー登録、もしくはログインする際にいくつか気をつけておかなければならないことがあります。

今回はそれらを自分への備忘録としても記事にしてお届けしたいと思います。

気をつけるべきこと

1.ユーザーテーブル

デフォルトで Laravel のログイン情報はメールアドレスとパスワードとなっています。
そのため、ユーザー登録をしようとするなら単純にフェイスブックなどから提供されるメールアドレスとランダムなパスワードを使って以下のようにしようとすると思います。

\App\User::create([
    'email' => $socialite_user->email,
    'password' => str_random()
]);

しかし、これでは今後ソーシャルログインのメールアドレスを変更されてしまった場合に違うメールアドレスが提供されることになるため同一のユーザーであってもメールアドレス変更後は再度新しいユーザーとして認識されることになってしまいます。

これを防止するためにはユーザーテーブル(もしくはソーシャルログイン専用テーブル)にログインに使用するサイトとユニークIDを保存し、ログインする際にはこれらで認証をする必要があります。

そこで migration に provider_name と provider_id などのようなカラムを追加します。

/**
* Run the migrations.
*
* @return void
*/
public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->string('password');
        $table->string('provider_name')->nullable();  // ←ここ。facebook や twitter などが入る
        $table->string('provider_id')->nullable();  // ←ここ。各サイトのユーザーID
        $table->rememberToken();
        $table->timestamps();
    });
}

※通常のユーザー登録の際は provider_name, provider_id は必要ないので nullbale() を付け加えています。

そして、ログインはこれら2つのカラムを利用してチェックを行います。
(※ただし、これではまだ未完成です。次の項目もチェックしてください)

$user = \App\User::where('provider_name', $driver)
    ->where('provider_id', $socialite_user->id)
    ->first();

2.provider_name と provider_id の2つだけでユーザーチェックをするとエラーが発生

先ほど追加した2つのカラムでのチェックだけでユーザー登録を実行するとエラーが発生する場合があります。
例えば以下の例を考えてみましょう。

1.ユーザ登録はフェイスブックを使った。
2.その後、ツイッターも面白そうなので登録した。
3.フェイスブックで登録したのを忘れてツイッターのソーシャルログインで認証を実行した(←エラーが出ます)

なぜなら、すでに登録されている provider_name と provier_id はフェイスブックのものなので、先ほどの where 句を使ったユーザーチェックでは「該当なし」となってしまいます。

該当なしとなると、プログラムの方ではユーザー登録をするはずです。
しかしそうなった場合、もしこのユーザーのフェイスブックとツイッターのメールアドレスが同じだった場合はどうなるでしょう。

そうです。
migration には email はユニーク設定がされていますのでエラーが発生してしまうわけです。
つまり、「もうすでにそのメールアドレスは登録されてるよ!」エラーですね。

そこでこれを回避するためには以下のようにメールアドレスでのチェックも orWhere で追加する必要があります。

$user = \App\User::where(function($query) use($socialite_user, $driver){

    $query->where('provider_name', $driver)
    ->where('provider_id', $socialite_user->id);

})
->orWhere('email', $socialite_user->email)
->first();

これで他のソーシャルログインを試されても問題ないでしょう。

3.ツイッターのソーシャルログインはメールアドレスをデフォルトで提供しない

これは少し面倒なのですが、ツイッターのソーシャルログインでメールアドレスを取得したい場合は以下の2つの情報を追加する必要があります。

1.プライバシーポリシーのURL
2.利用規約のURL

もしメールアドレスを取得したいのならこれらを Application Management の settings タブで登録し、さらに permissions タブの「Additional Permissions」で 「Request email addresses from users」にチェックを入れて保存しましょう。

以上、Socialte の注意すべき点のまとめでした。
できれば今後は Socialite の方でユーザー登録 or 自動ログインを自動的に行ってくれるメソッドなどを追加してくれると嬉しいなと思いつつ今回の記事を終了します

(もしかしてもう、ある???)