I am trying to override Devise's error message 'reset_password_token is invalid'
entirely. I would like it to read "password reset link has already been used."
How can I do this? There does not seen to be a field or keyword for this in devise.en.yml
.
Although the reset token from the reset password instructions email matches with the reset token from the database it returns an invalid token error on the changing password form. Database query expose that devise looks for a different token in the database.
It doesn't happen all the time. But some time it happens for users that they cannot reset their password as it shows Reset password token is invalid error. I got the same issue with @jimiguru I'm not really sure why the token saved in the db didn't match the reset token being retrieved in the email. can anybody help us with this? thanks!
To manually generate a reset password link using devise, the first step is to log in your server and launch the Rails console. Once in there, ask devise for a new reset password token. The call returns two values. The first is the raw token to use in the reset password URL query string, and the second is a hashed version of the token.
The reset_password_token attribute stores a string token that gets matched with a user and reset_password_sent_at, a datetime attribute that gets compared with Devise’s reset_password_within setting to note when the token should be invalidated. If you don’t have these attributes on the User model, you’ll need to add them before this will work.
A simpler solution than overwriting the passwords_controller, is simply to modify the view:
In app/views/devise/passwords/edit.html.haml (or your erb equivalent), Just put this conditional inside the form:
- if resource.errors[:reset_password_token].present?
.alert.alert-danger
This password reset URL has expired. You may have requested to reset your password more than once. Follow the link in the most recent email or
= link_to 'request to reset your password again.', new_user_password_path
And you may want to remove these two lines:
= f.error_notification
= f.full_error :reset_password_token
Reset password token is invalid
message is a validation error thrown while updating password, and is not a devise specific error ( for which the messages stored in devise.en.yml).
This validation happens in the devise/passwords_controller#update method. Code included below:
# PUT /resource/password
def update
self.resource = resource_class.reset_password_by_token(resource_params)
yield resource if block_given?
if resource.errors.empty?
resource.unlock_access! if unlockable?(resource)
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
set_flash_message(:notice, flash_message) if is_flashing_format?
sign_in(resource_name, resource)
respond_with resource, location: after_resetting_password_path_for(resource)
else
respond_with resource
end
end
The self.resource = resource_class.reset_password_by_token(resource_params)
line sets the resource.errors
object with the error message related to reset_password_token being invalid.
Inspecting the value of resource.errors
after this line will show a big hash ending with ... @messages={:reset_password_token=>["is invalid"]}
The devise_error_messages
method reformats this to say "Reset Password Token is invalid".
To change this message, the passwords controller should be customized and the update
method changed to have a different error message hash.
Steps would be as follows:
1) Customize the routes for passwords controller
# config/routes.rb
devise_for :users, :controllers => { :passwords => "passwords" }
2) Create the customized passwords controller
# app/controllers/passwords_controller.rb
class PasswordsController < Devise::PasswordsController
end
3) Customize the update method to change the error message:
# app/controllers/passwords_controller.rb
# Include the update method as it is fully, with the following changes in the else block:
def update
...
if resource.errors.empty?
...
else
if resource.errors.messages[:reset_password_token]
resource.errors.messages.delete(:reset_password_token)
resource.errors.messages[:password_reset_link] = ["has already been used"]
end
respond_with resource
end
More about Customizing Devise controllers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With