Devise «Le jeton de confirmation n’est pas valide» lorsque l’utilisateur s’inscrit

Utiliser Rails 4 et Devise 3.1.0 sur mon application Web. J’ai écrit un test de concombre pour tester l’inscription des utilisateurs. il échoue lorsque le lien “confirmer mon compte” est cliqué à partir de l’e-mail.

Scenario: User signs up with valid data # features/users/sign_up.feature:9 When I sign up with valid user data # features/step_definitions/user_steps.rb:87 Then I should receive an email # features/step_definitions/email_steps.rb:51 When I open the email # features/step_definitions/email_steps.rb:76 Then I should see the email delivered from "[email protected]" # features/step_definitions/email_steps.rb:116 And I should see "You can confirm your account email through the link below:" in the email body # features/step_definitions/email_steps.rb:108 When I follow "Confirm my account" in the email # features/step_definitions/email_steps.rb:178 Then I should be signed in # features/step_definitions/user_steps.rb:142 expected to find text "Logout" in "...Confirmation token is invalid..." (RSpec::Expectations::ExpectationNotMetError) ./features/step_definitions/user_steps.rb:143:in `/^I should be signed in$ 

Cette erreur est reproductible lorsque je m’inscris manuellement via le serveur Web, ce qui ne semble pas être un problème de concombre.

J’aimerais:

  • L’utilisateur pour pouvoir cliquer en un clic sur son compte via ce lien
  • Demander à l’utilisateur de restr connecté après avoir confirmé son compte

J’ai configuré:

  • Le dernier code Devise, de GitHub (3.1.0, réf 041fcf90807df5efded5fdcd53ced80544e7430f)
  • Une classe d’ User qui implémente confirmable
  • Utiliser le contrôleur de confirmation par défaut (je n’ai pas défini mon propre contrôleur personnalisé)

J’ai lu ces articles:

  • Devise confirmation_token est invalide
  • Devise 3.1: maintenant avec plus de valeurs par défaut sécurisées
  • GitHub Issue – Devise confirmation_token invalide

Et ont essayé:

  • Définir config.allow_insecure_tokens_lookup = true dans mon initialiseur Devise, ce qui génère une erreur “méthode inconnue” au démarrage. De plus, il semble que ce soit seulement une solution temporaire, donc je voudrais éviter de l’utiliser.
  • Purgé ma firebase database et commencé à partir de zéro (donc aucun ancien jeton n’est présent)

Mettre à jour:

Vérification du jeton de confirmation stocké sur l’ User après l’enregistrement. Le jeton de courrier électronique correspond au jeton de firebase database. Selon les articles ci-dessus, le nouveau comportement de Devise dit non supposé, et qu’il devrait générer un second jeton basé sur le jeton de l’e-mail. Ceci est suspect. Exécuter User.confirm_by_token('[EMAIL_CONFIRMATION_TOKEN]') renvoie un utilisateur dont les erreurs sont définies “@messages = {: confirmation_token => [” est invalide “]}”, ce qui semble être la source du problème.

Les jetons incompatibles semblent être au cœur du problème; en exécutant le code suivant dans la console pour modifier manuellement la confirmation de l’utilisateur, la confirmation réussit:

 new_token = Devise.token_generator.digest(User, :confirmation_token, '[EMAIL_TOKEN]') u = User.first u.confirmation_token = new_token u.save User.confirm_by_token('[EMAIL_TOKEN]') # Succeeds 

Alors, pourquoi enregistre-t-on en premier lieu le mauvais jeton de confirmation à la firebase database? J’utilise un contrôleur d’enregistrement personnalisé … Peut-être y a-t-il quelque chose qui provoque un réglage incorrect?

routes.rb

  devise_for :users, :path => '', :path_names => { :sign_in => 'login', :sign_out => 'logout', :sign_up => 'register' }, :controllers => { :registrations => "users/registrations", :sessions => "users/sessions" } 

users / registrations_controller.rb :

 class Users::RegistrationsController < Devise::RegistrationsController def create # Custom code to fix DateTime issue Utils::convert_params_date_select params[:user][:profile_attributes], :birthday, nil, true super end def sign_up_params # TODO: Still need to fix this. Strong parameters with nested attributes not working. # Permitting all is a security hazard. params.require(:user).permit! #params.require(:user).permit(:email, :password, :password_confirmation, :profile_attributes) end private :sign_up_params end 

Donc, la mise à niveau vers Devise 3.1.0 a laissé des «croupes» dans un point que je n’avais pas touché depuis un moment.

Selon ce billet de blog , vous devez modifier votre logiciel de messagerie Devise pour utiliser @token au lieu de l’ancien @resource.confirmation_token .

Trouvez ceci dans app/views//mailer/confirmation_instructions.html.erb et changez-le en quelque chose comme:

 

Welcome <%= @resource.email %>!

You can confirm your account email through the link below:

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

Cela devrait résoudre tous les problèmes de confirmation liés aux jetons que vous rencontrez. Cela est susceptible de résoudre tous les problèmes de délocking ou de réinitialisation du mot de passe.

Un de mes amis vient de trouver cette question et m’a envoyé un e-mail pour me demander si je l’avais compris, ce qui m’a rappelé que je n’ai jamais soumis ma propre réponse, alors voilà 🙂

J’ai fini par réinitialiser le jeton et utiliser send pour obtenir le jeton brut. C’est moche, mais ça fonctionne dans un coup de poing pour le devise (3.5.1) .

 26 it "should auto create org" do 27 email = FG.generate :email 28 visit new_user_registration_path 29 fill_in :user_name, with: 'Ryan Angilly' 30 fill_in :user_user_provided_email, with: email 31 fill_in :user_password, with: '1234567890' 32 33 expect do 34 click_button 'Continue' 35 end.to change { Organization.count }.by(1) 36 37 expect(page.current_path).to eq(confirmation_required_path) 38 u = User.where(email: email).first 39 u.send :generate_confirmation_token 40 email_token = u.instance_variable_get(:@raw_confirmation_token) 41 u.save! 42 os = u.organizations 43 expect(os.size).to eq(1) 44 visit user_confirmation_path(confirmation_token: email_token) 45 o = os.first 46 47 u.reload 48 expect(u.confirmed?) 49 expect(page.current_url).to eq(organization_getting_started_url(o)) 50 end 

A compter de la version 3.5.2, le jeton de confirmation n’est plus digéré lors du processus de confirmation. Cela signifie que le jeton dans le courrier électronique correspondra au jeton dans la firebase database.

J’avais encore des problèmes avec les confirmations après avoir compris cela, mais dans mon cas, cela s’est avéré être un bug que j’ai introduit lorsque j’ai find_first_by_auth_conditions . En corrigeant le bug que j’ai introduit dans cette méthode, j’ai corrigé mes erreurs avec une confirmation.