Solution
Thanks to this gist form Steven Harman, I got it working. devise_mail_helpers.rb
module Features
module MailHelpers
def last_email
ActionMailer::Base.deliveries[0]
end
# Can be used like:
# extract_token_from_email(:reset_password)
def extract_token_from_email(token_name)
mail_body = last_email.body.to_s
mail_body[/#{token_name.to_s}_token=([^"]+)/, 1]
end
end
end
I added the file devise_mail_helpers.rb
to the same folder as the features specs and wrote this spec.
require 'devise_mail_helpers.rb'
include Features
include MailHelpers
describe "PasswordResets" do
it "emails user when requesting password reset" do
user = FactoryGirl.create(:user)
visit root_url
find("#login_link").click
click_link "Forgot your password?"
fill_in "Email", :with => user.email
click_button "Send instructions"
current_path.should eq('/users/sign_in')
page.should have_content("You will receive an email with instructions about how to reset your password in a few minutes.")
last_email.to.should include(user.email)
token = extract_token_from_email(:reset_password) # Here I call the MailHelper form above
visit edit_password_url(reset_password_token: token)
fill_in "user_password", :with => "foobar"
fill_in "user_password_confirmation", :with => "foobar1"
find('.signup_firm').find(".submit").click
page.should have_content("Password confirmation doesn't match Password")
end
end
This takes care of the specs, to make it work in the browser look at Dave's answer below.
Original Question
In my rails 4 app, I've upgraded devise to 3.1 and ran rails s
, then I got this:
`raise_no_secret_key': Devise.secret_key was not set.
Please add the following to your Devise initializer: (RuntimeError)
config.secret_key = '--secret--'
I added the secret key to the devise initializer.
After this I get the following error when I try to reset the password
Reset password token is invalid
It seems like the token that gets sent in the email is not correct. Everything else is working. I logging in and out like a warm knife trough butter.
Update
Now I guess that it's got to be something with the encryption of the reset_password_token
Here from the feature spec:
user = FactoryGirl.create(:user,
:reset_password_token => "something",
:reset_password_sent_at => 1.hour.ago)
visit edit_password_url(user, :reset_password_token =>
user.reset_password_token)
fill_in "user_password", :with => "foobar"
click_button "Change my password"
page.should have_content("Password confirmation doesn't match Password")
the error occured is:
Failure/Error: page.should have_content
("Password confirmation doesn't match Password")
expected to find text "Password confirmation doesn't match Password" in
"Reset password token is invalid"
Any ideas on what I am missing?
FYI, if you're trying to send a reset password token via another means (i.e. different mailer), you can use code like this (dug out of Devise source), in your User class:
In your devise reset password template make sure following content should correct:
=link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @token)
I had this error on specs. I was trying to manually set
reset_password_token
on User so I could just pass in the token to theedit_user_password_path
. However, the reset tokens are hashed, so setting it manually won't work. Oops! To avoid this error, I setreset_token
equal to the actual token generated which is returned byuser.send_reset_password_instructions
.Working spec:
You commented on my similar question a bit ago, and I found an answer that might help you as well.
Upgrading to Devise 3.1.0 left some 'cruft' in a view that I hadn't touched in a while. According to this blog post, you need to change your Devise mailer to use
@token
instead of the old@resource.confirmation_token
.Find this in
app/views/<user>/mailer/reset_password_instructions.html.erb
and change it to something like:This should fix any token-based confirmation problems you're having. This is likely to fix any unlock or confirmation token problems as well.
I guess you've upgraded Devise to v3.1 not v3.01, because of
config.secret_key
. So I think it is somehow related to new devise feature - secret key.I found two commits for secret key feature that can be helpful to better understanding: https://github.com/plataformatec/devise/commit/32648027e282eb4c0f4f42e9c9cc0c961765faa8 https://github.com/plataformatec/devise/commit/d56641f514f54da04f778b2a9b816561df7910c2
Probably you will find something useful for you on http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/ as well.
Also you can grep reset_password_token on https://github.com/plataformatec/devise/compare/v3.0...v3.1.0.
EDIT
Read on http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/:
As others have noted: the reason is that the view which generates the mail which includes the reset password link needs to be changed.
I saw this error because I was still using the
devise-i18n-views
gem, which generates the old link. Removing that gem and relying on the views which are now a part of thedevise-i18n
gem solved the problem for me.