Search code examples
ruby-on-railsdevisereset-password

Custom generated reset password token not recognized


I have a rails application in which the super-admin can create new users manually. I need to send a email to the new user to allow to reset his password and to connect to his space.

So I'm trying to generate manually un edit_user_password_path with reset_password_token and to send it on user's email :

def create
  raw, reset_password_token = Devise.token_generator.generate(
    User, :reset_password_token
  )
  @user = User.new(user_params)
  @user.reset_password_token = reset_password_token
  @user.reset_password_sent_at = Time.now.utc

  reset_password_url = Rails.configuration.endpoints['front'].to_s + Rails.application.routes.url_helpers.edit_user_password_path(reset_password_token: reset_password_token)
  # it generates http://localhost:3000/users/password/edit?reset_password_token=my_token_sent_by_email link, so it's good

  if @user.save(validate: false)
    AdminMailer.welcome_email(@user, reset_password_url).deliver
    render 'index'
  else
    render 'new'
  end
end

My user_params method is a private method :

def user_params
  params.require(:user).permit(:name, :email, :role)
end

But when I follow the generated edit_password_link and I try to reset my password I have the token_invalid error from devise.

When I try to do this in Rails console :

User.find_by(reset_password_token, my_token_sent_by_email) 

I find the record from the database.

But when I initialize an reset password link for the user who wants to change his password with devise's send_reset_password_instructions it works without any problems :

def send_pass
  @user = User.find(params[:id])
  @user.send_reset_password_instructions
  redirect_back(fallback_location: root_path)
end

Can anybody explain what error I do please ? Thanks for all answers


Solution

  • So, finally I've find the solution.

    When we generate the tokens with

    raw, reset_password_token = Devise.token_generator.generate(User, :reset_password_token)
    

    we need to save the reset_password_token in the database (with reset_password_sent_at of corse, but we need to send the raw in the edit_password_link :

    reset_password_url = Rails.configuration.endpoints['front'].to_s + Rails.application.routes.url_helpers.edit_user_password_path(reset_password_token: raw)