web-dev-qa-db-fra.com

La mise à niveau vers la version 3.1 => la réinitialisation du jeton de mot de passe n'est pas valide

Solution

Grâce à cela Gist de Steven Harman, je l'ai fait fonctionner. 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

J'ai ajouté le fichier devise_mail_helpers.rb dans le même dossier que les spécifications des fonctionnalités et écrit cette spécification.

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

Cela prend en charge les spécifications, pour le faire fonctionner dans le navigateur, regardez la réponse de Dave ci-dessous.

Question d'origine

Dans mon Rails 4, j'ai mis à niveau la version 3.1 et exécuté Rails s, alors j'ai obtenu ceci:

`raise_no_secret_key': Devise.secret_key was not set. 
 Please add the following to your Devise initializer: (RuntimeError)
 config.secret_key = '--secret--'

J'ai ajouté la clé secrète à l'initialiseur de devise.

Après cela, j'obtiens l'erreur suivante lorsque j'essaie de réinitialiser le mot de passe

Reset password token is invalid

Il semble que le jeton envoyé dans l'e-mail ne soit pas correct. Tout le reste fonctionne. Je me connecte et me déconnecte comme un couteau au beurre chaud.

Mise à jour

Maintenant, je suppose que cela doit être quelque chose avec le cryptage du reset_password_token Voici la spécification de la fonctionnalité:

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")

l'erreur survenue est:

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"

Des idées sur ce qui me manque?

40
Andreas Lyngstad

Vous avez commenté ma question similaire il y a un peu, et j'ai trouvé une réponse qui pourrait également vous aider.

La mise à niveau vers Devise 3.1.0 a laissé une certaine "cruauté" dans une vue que je n'avais pas touchée depuis un moment. Selon cet article de blog , vous devez changer votre logiciel de messagerie Devise pour utiliser @token au lieu de l'ancien @resource.confirmation_token.

Trouvez ceci dans app/views/<user>/mailer/reset_password_instructions.html.erb et remplacez-le par quelque chose comme:

<p>Hello <%= @resource.email %>!</p>
<p>Someone has requested a link to change your password, and you can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_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>

Cela devrait résoudre tous les problèmes de confirmation basés sur des jetons que vous rencontrez. Cela est également susceptible de résoudre tout problème de déverrouillage ou de jeton de confirmation.

91
David Elner

Pour info, si vous essayez d'envoyer un jeton de réinitialisation de mot de passe via un autre moyen (c'est-à-dire un autre mailer), vous pouvez utiliser un code comme celui-ci (extrait de la source Devise), dans votre classe d'utilisateur:

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

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

  Notifier.signup_notification(contactable: self, token: raw).deliver
end
8
Pogoapp

J'ai eu cette erreur sur les spécifications. J'essayais de définir manuellement reset_password_token sur l'utilisateur pour que je puisse simplement passer le jeton au edit_user_password_path. Cependant, les jetons de réinitialisation sont hachés, donc le définir manuellement ne fonctionnera pas. Oups! Pour éviter cette erreur, j'ai défini reset_token égal au jeton généré qui est retourné par user.send_reset_password_instructions.

Spécifications de travail:

require 'spec_helper'

feature 'User resets password' do
  scenario 'fills out reset form' do
    user = create(:user)
    reset_token = user.send_reset_password_instructions
    new_password = 'newpassword!'
    visit edit_user_password_path(user, reset_password_token: reset_token)

    fill_in :user_password, with: new_password
    fill_in :user_password_confirmation, with: new_password
    click_button 'Change my password'

    expect(page).to have_content(
      'Your password was changed successfully. You are now signed in.'
    )
  end
end
7
Neal

Je suppose que vous avez mis à niveau Devise vers la v3.1 et non la v3.01, à cause de config.secret_key. Je pense donc que cela est en quelque sorte lié à la nouvelle fonctionnalité de conception - clé secrète.
J'ai trouvé deux validations pour une fonctionnalité de clé secrète qui peut être utile pour une meilleure compréhension: https://github.com/plataformatec/devise/commit/32648027e282eb4c0f4f42e9c9cc0c961765faa8https://github.com/plataformatec/devise/commit/d56641f514f54da04f778b2a9b816561df7910c2

Vous trouverez probablement quelque chose d'utile pour vous sur http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/ ainsi .
Vous pouvez également grep reset_password_token sur https://github.com/plataformatec/devise/compare/v3.0 ... v3.1. .

[~ # ~] modifier [~ # ~]
Lisez la suite http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/ :

  • L'envoyeur Devise reçoit désormais un argument de jeton supplémentaire sur chaque méthode. Si vous avez personnalisé l'expéditeur Devise, vous devrez le mettre à jour. Toutes les vues des expéditeurs doivent également être mises à jour pour utiliser @token, comme indiqué ici , au lieu d'obtenir le jeton directement de la ressource;
7
Sergey Alekseev

Comme d'autres l'ont noté: la raison en est que la vue qui génère le courrier qui inclut le lien de réinitialisation du mot de passe doit être modifiée.

J'ai vu cette erreur car j'utilisais toujours le devise-i18n-views gem, qui génère l'ancien lien. Supprimer ce joyau et s'appuyer sur les vues qui font maintenant partie du devise-i18n gem a résolu le problème pour moi.

2
eikes

Dans votre modèle de réinitialisation de mot de passe, assurez-vous que le contenu suivant doit être correct:

= link_to 'Changer mon mot de passe', edit_password_url (@resource,: reset_password_token => @token)

1
SaraVanaN