8
votes

My User.rb:

class User < ActiveRecord::Base

    devise :database_authenticatable, :registerable,:confirmable,:token_authenticatable,
     :recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:name]

My routes:

devise_for :users, :controllers => { :sessions => "sessions", :confirmations => "confirmations", :passwords => "passwords", :registrations => "registrations" }

My ConfirmationsController is a standard controller but with different redirect.

I have link on my email like:

/users/confirmation?confirmation_token=167bad44a15e02b0bd570b51e1bf927b88368d8855d92b9833a24017a2bad4be

In database user has

confirmation_token:167bad44a15e02b0bd570b51e1bf927b88368d8855d92b9833a24017a2bad4be

But when i click on that link i only see page with:

Resend confirmation instructions
 Confirmation token is invalid

What i dont do - what else i have to set.

CONFIRMATIONCONTROLLER:

def resource_params
 params.require(:user).permit(:confirmation_token)
   end
   private :resource_params


  def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])

if resource.errors.empty?
  set_flash_message(:notice, :confirmed) if is_navigational_format?
  sign_in(resource_name, resource)
  session['new_user'] = true
  respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
  respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
end
  end

  protected
    # The path used after resending confirmation instructions.
    def after_resending_confirmation_instructions_path_for(resource_name)
      new_registration_path(resource_name)
    end

I say "standard controller" because when i remove it and do not use custom controller problem is that same.

3
Post your "standard" overridden controller code.TheIrishGuy
and? Is there some bug or what... i change token to abcde in database and in url - and nothing changeWordica
This might not solve the whole problem, but if you just want to redirect to a different path after confirmation you should not copy/paste the entire method. You should override the protected method after_confirmation_path_for to return the path you want.Ross Allen
yes it doesnt change nothing - confirmed_at: nil . Devise just cant confirm account with tokenWordica

3 Answers

17
votes

Which version of devise are you using? If you're on 3.1.0 or higher, this behavior is expected:

CHANGELOG.md

The tokens that are stored in the database are not supposed to match the tokens that you send in the confirmation e-mails. See devise/lib/devise/models/confirmable.rb, which now contains the following:

def confirm_by_token(confirmation_token)
  original_token     = confirmation_token
  confirmation_token = Devise.token_generator.digest(self, :confirmation_token, confirmation_token)

  confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)

As you can see, the token that you pass in via query string params is consumed by the Devise.token_generator, and the result of that operation is what's compared with the token in the database to discover the user record.

It looks like it's temporarily possible (in 3.1 but not 3.2) to turn this off by setting

config.allow_insecure_token_lookup = true

in your devise initializer. But the default behavior has been changed to make devise more secure. See this blog post for a complete rundown of the security improvements in devise 3.1, including this change.

5
votes

You can use the solution below (setting config.allow_insecure_token_lookup = true) but, according to the Devise changelog, this will be only available temporarily.

The problem likely arose because you ran the devise generator to dump all of their views into yours back before they made these changes. Then you updated your Devise gem and all the back end stuff changed but your views didn't. Now all your devise-related views and mailers are out of date and won't work with the new token styles.

You can see the new emails at: https://github.com/plataformatec/devise/tree/master/app/views/devise/mailer. The major change is changing this line:

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

to

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

The main difference is @resource.confirmation_token becomes just @token.

2
votes

I change @resource.confirmation_token to @token then it works.