GGizmos
GGizmos

Reputation: 3775

Overriding Devise SessionsController#Create and create view - and authentication fails

I have a user login page which was adapted from the devise login view and I am overriding the controller because I need to perform several tasks on login, but I can't get past step 1 (warden authentication.

Inside Users::SessionController < Devise::SessionsController, I simply have

def create
   super
   [...other post authentication code]
end

Debugging into super.create I can see that it calls

 self.resource = warden.authenticate!(auth_options) 

but it never retu8rns from the call to super. Somehow the warden.authenticate! call appears to hijack the create method ends up re-rendering the login page.

I see that the auth_options parameters contains only a hash:

 => {:scope=>:user, :recall=>"users/sessions#new"}

Maybe something is wrong there, as I would have thought the email and password would need to be passed somehow, but Warden is a bit of a mystery anyway, not really sure what should be in those auth options. So I don't really understand what is being authenticated, but the warden is a mystery to me anyway.

Here is the params collection that's coming through to the create method.

 <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"EJ[...]mA==", 
"email"=>"[email protected]", "password"=>"Qrxt5d3", "commit"=>"Log in", "controller"=>"users/sessions", "action"=>"create"} 
permitted: false>

I can confirm that the password is correct using user.valid_password?("Qrxt5d3")

I checked the parameter names on the original view code supplied by the gem, and it seems like the params of interest are called "email" and "password" so not obvious to me what is going wrong here.

Thanks for any help.

Upvotes: 1

Views: 3098

Answers (2)

Giridharan
Giridharan

Reputation: 568

try this this works fine for me!

Routes

devise_for :users, controllers: { sessions: 'users/sessions',
                    registrations: 'users/registrations'
                  }

Controller

app\controllers\users\sessions_controller.rb

   class Users::SessionsController < Devise::SessionsController
    def create
    @admin = User.find_by(email:params["session"]["email"])
      if @admin.valid_password?(params["session"]["password"])
             sign_in(:user, @admin)
             redirect_to root_path
      else
              flash[:error] = "Invalid Password." 
              redirect_back(fallback_location: root_path)
      end
    end
  end

View

app\views\users\sessions\new.html.erb

<%= form_for :session, url: user_session_path do |f| %> 
    <%= f.email_field :email%>
    <%= f.password_field :password%>
    <%= f.submit'login'%>
   <%end%>

Upvotes: 1

GGizmos
GGizmos

Reputation: 3775

Apparently the issue is that warden.authenticate!(auth_options) does some sort of immediate redirect to new when authentication fails.

The reason authentication was failing in my case was because I had :confirmable in my model and the user name hadn't been confirmed yet. Removing that from the user model, then authentication succeeded.

(I would have thought that authenticate! might raise an error or return false or something on failure but instead it just redirects to :new.

Upvotes: 2

Related Questions