ログインに失敗する
超初心者的なミスです。
恥ずかしいのですが、自分への備忘録として。
- devise+Omniauthを導入
- facebookとtwitterログイン機能を実装。
- twitterログインが確認できたのでherokuにデプロイ。
・・・あれ?なぜかfacebookのログインができない(滝汗)
コードがほとんど共通なのに、twitterだと普通に入れるというナゾ現象。
FB側でのコールバック設定や、API-KEYなどの環境変数を疑いましたが、FB認証は通っている様子。コントローラーまで処理が戻ってきた上ではじかれ、新規登録画面に飛ばされるのだが、はて。
コード
callbackを担当するコントローラーはこんな感じ。
こちらのサンプルにをほぼほぼそっくり真似た、標準的な書き方かなと思います。
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
の登録がはねられていました。(´∀`;)
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から受け取る情報を最低限に絞り、プロフィール関係は別途入力してもらう(ここはここでバリデーションをかけるけど、認証とは分ける)という手もあるのかな、とおもいました。
二段階にすると、ユーザーの負担は増えそうですね。どうなんでしょうか?
こんな残念な間違いをする方はいないとは思いつつ、億が一、誰かの役に立てたらということで置いておきます。