Rails
devise

[Rails]deviseでreset_password_tokenが不正と言われる


先に結論

devise-i18n-viewsの影響で、ユーザーのパスワード変更が出来なかった。

READMEにもかいてあるが、このgemはdevise-i18nにマージされたのでこっちを使うようにする。


環境


  • rails 5.2.3

  • devise 4.6.2

  • devise-i18n 1.8.0

  • devise-i18n-views 今回これが要らなかった話


何が起こった

deviseで管理しているモデルのパスワード変更をしようとしたらトークンが不正だと言われる。


  1. ログイン画面から「パスワードを忘れた」をクリック

  2. 登録されているメールアドレスを入力して送信

  3. 確認メール内のリンクをクリック

  4. パスワード再設定のフォームが開くので、新しいパスワードを入力


  5. reset_password_tokenが不正だと言われる orz


調査

「rails devise reset_password_by_token invalid」とかでググってみると、この手の話題は幾つか見つかった。

このissueとか参考になった。

具体的に、deviseはreset_password_tokenを作成するときに、以下のようなコードになっていた。

def set_reset_password_token

raw, enc = Devise.token_generator.generate(self.class, :reset_password_token)

self.reset_password_token = enc
self.reset_password_sent_at = Time.now.utc
save(validate: false)
raw
end


https://github.com/plataformatec/devise/blob/master/lib/devise/models/recoverable.rb#L89


で、この戻り値 rawを受け取ってパスワードリセットメールを送信している

def send_reset_password_instructions

token = set_reset_password_token
send_reset_password_instructions_notification(token)

token
end

この処理を見ると、実際はDBに保存されている reset_password_tokenの値とパスワードリセットのメールに記載されているreset_password_tokenは違うものだった

localhost:3000/users/password/edit?reset_password_token=vu9utDw1Mri848sEqPYf ←これ

issueにも書いてある通り、このリンクが書いてあるのはviewのmailer配下なので、問題があるとすればここだと思った。

が、今回はdeviseのファイルを翻訳するために


  • devise-i18n

  • devise-i18n-views

というgemを入れていた。

devise-i18n-viewsのソースコードを調べたところ、 ここが原因となっていた。

(Devise::VERSION.start_with?('3.') ? @token : @resource.reset_password_token)

deviseは4.6.2なのでfalseが実行されていた。。。


対応


  1. Gemfileからdevise-i18n-viewsを削除

  2. bundle update

  3. bundle clean