web-dev-qa-db-fra.com

Rails 4 + Devise: la réinitialisation du mot de passe génère toujours une erreur "Le jeton n'est pas valide" sur le serveur de production, mais fonctionne correctement localement.

J'ai une application Rails 4 configurée pour utiliser Devise et je rencontre un problème de réinitialisation du mot de passe. J'ai le mailer mis en place, et l'e-mail de réinitialisation du mot de passe envoie bien. Le lien fourni a le correct reset_password_token qui lui est attribué, que j'ai vérifié avec cette base de données. Cependant, lorsque je soumets le formulaire avec des mots de passe correctement formatés, un message d'erreur indiquant que le jeton de réinitialisation n'est pas valide s'affiche. 

Cependant, le même code fonctionne correctement localement via Rails s. L'email envoie, et je peux réellement réinitialiser le mot de passe. Le code que j'utilise n'est que le code standard de Devise, je ne l'ai jamais remplacé. 

Peut-être que c'est quelque chose avec Apache? Je ne suis pas trop au courant. Quelqu'un a-t-il une idée? 

47
justindao

En plus du correctif de doctororange, si vous écrasez resource.find_first_by_auth_conditions, vous devez indiquer le cas où warden_conditions contient un reset_password_token au lieu d'un email ou d'un nom d'utilisateur.

EDIT: Elaborer:

Devise ajoute des fonctionnalités à votre modèle lorsque vous indiquez «Concevoir: enregistrable,: traçable, ...». 

Dans votre modèle utilisateur (ou administrateur, etc.), vous pouvez écraser la méthode Devise nommée find_first_by_auth_conditions. Cette méthode spéciale est utilisée par la logique Devise pour localiser l’enregistrement auquel on tente d’être connecté. Devise transmet certaines informations dans un paramètre appelé warden_conditions. Celui-ci contiendra un email, un nom d'utilisateur, un reset_password_token ou tout ce que vous ajouterez à votre formulaire de connexion à la carte (comme un identifiant de compte).

Par exemple, vous pourriez avoir quelque chose qui ressemble à ceci:

(app/models/user.rb)
class User

  ...

  def self.find_first_by_auth_conditions warden_conditions
    conditions = warden_conditions.dup

    if (email = conditions.delete(:email)).present?
      where(email: email.downcase).first
    end
  end

end

Cependant, le code ci-dessus annulera la fonctionnalité de réinitialisation du mot de passe, car le système utilise un jeton pour localiser l'enregistrement. L'utilisateur n'entre pas d'e-mail, il entre le jeton via une chaîne de requête dans l'URL, qui est transmise à cette méthode pour essayer de trouver l'enregistrement.

Par conséquent, lorsque vous écrasez cette méthode spéciale, vous devez la rendre plus robuste pour prendre en compte le cas de réinitialisation du mot de passe:

(app/models/user.rb)
class User

  ...

  def self.find_first_by_auth_conditions warden_conditions
    conditions = warden_conditions.dup

    if (email = conditions.delete(:email)).present?
      where(email: email.downcase).first
    elsif conditions.has_key?(:reset_password_token)
      where(reset_password_token: conditions[:reset_password_token]).first
    end
  end

end
11
MaximusDominus

Si vous prenez l'URL d'un journal, il peut ressembler à ceci:

web_1      | <p><a href=3D"http://localhost:3000/admin/password/edit?reset_password_to=
web_1      | ken=3DJ5Z5g6QNVQb3ZXkiKjTx">Change password</a></p>

Dans ce cas, utiliser 3DJ5Z5g6QNVQb3ZXkiKjTx comme jeton ne fonctionnera pas car =3D est en réalité un caractère = codé.

Dans ce cas, vous devez utiliser J5Z5g6QNVQb3ZXkiKjTx (avec 3D supprimé)

5
ybart

Il peut également être utile de noter (en plus de la publication suivante de @ doctororange) si vous utilisez une vue personnalisée de l’éditeur de courrier de confirmation.

Le lien dans la vue a également changé ici. C'est le nouveau code de lien:

<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>

C'est le code de lien OLD:

<p><%= link_to 'Confirm my account', user_confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %></p>
0
pixelearth