From ab790836968cbe8014a98417c6dfc027413b1173 Mon Sep 17 00:00:00 2001 From: Diego Rossini Vieira Date: Tue, 27 Sep 2016 19:34:01 -0300 Subject: [PATCH] Prevent password reset token leak via HTTP referer --- app/controllers/devise/passwords_controller.rb | 13 +++++++++++-- test/integration/recoverable_test.rb | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/controllers/devise/passwords_controller.rb b/app/controllers/devise/passwords_controller.rb index f4291c76..c197a885 100644 --- a/app/controllers/devise/passwords_controller.rb +++ b/app/controllers/devise/passwords_controller.rb @@ -24,7 +24,13 @@ class Devise::PasswordsController < DeviseController def edit self.resource = resource_class.new set_minimum_password_length - resource.reset_password_token = params[:reset_password_token] + + if params[:reset_password_token] + session[:reset_password_token] = params[:reset_password_token] + redirect_to edit_user_password_url + end + + resource.reset_password_token = session[:reset_password_token] end # PUT /resource/password @@ -41,6 +47,7 @@ class Devise::PasswordsController < DeviseController else set_flash_message!(:notice, :updated_not_active) end + session[:reset_password_token] = nil respond_with resource, location: after_resetting_password_path_for(resource) else set_minimum_password_length @@ -60,7 +67,9 @@ class Devise::PasswordsController < DeviseController # Check if a reset_password_token is provided in the request def assert_reset_token_passed - if params[:reset_password_token].blank? + reset_token = session[:reset_password_token] || params[:reset_password_token] + + if reset_token.blank? set_flash_message(:alert, :no_token) redirect_to new_session_path(resource_name) end diff --git a/test/integration/recoverable_test.rb b/test/integration/recoverable_test.rb index f35a46b7..eb70b50f 100644 --- a/test/integration/recoverable_test.rb +++ b/test/integration/recoverable_test.rb @@ -22,7 +22,7 @@ class PasswordTest < Devise::IntegrationTest def reset_password(options={}, &block) unless options[:visit] == false visit edit_user_password_path(reset_password_token: options[:reset_password_token] || "abcdef") - assert_response :success + assert_current_url '/users/password/edit' end fill_in 'New password', with: '987654321'