Posted at

(Omniauth)ソーシャルログインでハマる

More than 1 year has passed since last update.


ログインに失敗する

超初心者的なミスです。

恥ずかしいのですが、自分への備忘録として。


  1. devise+Omniauthを導入

  2. facebookとtwitterログイン機能を実装。

  3. twitterログインが確認できたのでherokuにデプロイ。

・・・あれ?なぜかfacebookのログインができない(滝汗)

コードがほとんど共通なのに、twitterだと普通に入れるというナゾ現象。

FB側でのコールバック設定や、API-KEYなどの環境変数を疑いましたが、FB認証は通っている様子。コントローラーまで処理が戻ってきた上ではじかれ、新規登録画面に飛ばされるのだが、はて。


コード

callbackを担当するコントローラーはこんな感じ。

こちらのサンプルにをほぼほぼそっくり真似た、標準的な書き方かなと思います。


omniauth_callbacks_controller.rb


def facebook
auth = request.env["omniauth.auth"]
@user = User.where(provider: auth.provider, provider_uid: auth.uid).first
unless @user
@user = User.create(
name: auth.info.name,
email: fake_email(auth), # (ダミーのメールアドレスを生成)
provider: auth.provider,
provider_token: auth.credentials.token,
provider_uid: auth.uid,
password: Devise.friendly_token[0,20],
)
end

if @user.persisted? # 以下はログイン処理
set_flash_message(:notice, :success, kind: "Facebook") if is_navigational_format?
sign_in_and_redirect @user, event: :authentication
else # 失敗した場合
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end


最後の条件分岐で、新規登録画面にリダイレクトされてしまっている模様。

なおUserはdeviseモデル名で、デフォルトの設定(emailとpassword)以外に、nameというカラムが入っている。


原因

自分で書いたバリデーションで@userの登録がはねられていました。(´∀`;)


user.rb

  VALID_NAME =  /\A[a-zA-Z0-9_]+\z/

validates :name, presence: true, uniqueness: true, length: {minimum: 4, maximum: 20}, format: { with: VALID_NAME }

request.env['omniauth.auth']入っているデータ例を見るとわかるのですが、nameにはスペースが入っています。(しかも名前はアルファベットとは限らない。私の場合、漢字・・)

twitterだと英数字のアカウント名が返ってくるので、問題なく通っていたのでした。

ソーシャルログインプロセスのエラーなので、原因箇所の特定に少し手間取ったことと、同種のエラーがどんだけググっても出ない(そりゃそうだ)のでハマりました。


教訓

当たり前すぎますが、

「ソーシャルログインで帰ってくるデータは向こうの仕様に左右される」

・・・当たり前ですね。

以前にはfacebookがデフォルトでemailを返さなくなった変更もあったようだし、気をつけたい。

素人なりに考えられる対策としては、ログイン認証でapiから受け取る情報を最低限に絞り、プロフィール関係は別途入力してもらう(ここはここでバリデーションをかけるけど、認証とは分ける)という手もあるのかな、とおもいました。

二段階にすると、ユーザーの負担は増えそうですね。どうなんでしょうか?

こんな残念な間違いをする方はいないとは思いつつ、億が一、誰かの役に立てたらということで置いておきます。