I've been experiencing this weird error on the production version of my rails site for a while now. This does not occur locally, frustrating my debugging efforts.
I have followed the recommendations made in the following SO questions:
Upgrading to devise 3.1 => getting Reset password token is invalid Rails 4 + Devise: Password Reset is always giving a "Token is invalid" error on the production server, but works fine locally.
Specifically, changing my reset_password_instructions.html.erb
file to:
<p>Hello <%= @resource.email %>!</p>
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_user_password_url(@resource, :reset_password_token => @token) %></p>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>
I am using the following gems:
devise (3.5.9)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5)
responders
thread_safe (~> 0.1)
warden (~> 1.2.3)
When I create a test user on the production site, then click "forgot my password", it generates a reset token on the server (which I can see as XYZ123 via Rails Console).
If I create, via Rails Console, a token generator (Devise::TokenGenerator.new) with our secret key as per the Devise source, I am able to convert the token in the link (raw) emailed to the user to the reset token stored in the database. These match exactly, and if I use "User.find_or_initialize_with_error_by" in the rails console on production it is able to correctly find the user associated with the token. Of course, I'm doing this all manually following the devise source code so perhaps I'm doing something that the code isn't.
Does anyone have any theory as to why this might happen? In addition, the URLs being generated by my website for the password reset email are like:
http://www.WEBSITE.com/users/password/edit.<USER_ID>?reset_password_token=<CORRECT_RAW_RESET_PASSWORD_TOKEN>?reset_password_token=<CORRECT_RAW_RESET_PASSWORD_TOKEN>
Not sure why the reset_password_token param is included twice in this - in the email I receive via Gmail it is only included once.