3

I have a very simple sign_in page for a devise user. Upon submitting incorrect data, the log shows a '401 Unauthorized' and redirects me back to the sign_in page. I couldn't figure out a way to show error messages to the user.

I looked at devise::sessions_controller#create which is as follows,


 # POST /resource/sign_in
  def create
    resource = warden.authenticate!(auth_options)
    set_flash_message(:notice, :signed_in) if is_navigational_format?
    sign_in(resource_name, resource)
    respond_with resource, :location => after_sign_in_path_for(resource)
  end

  def auth_options
    { :scope => resource_name, :recall => "#{controller_path}#new" }
  end  

The flow gets interrupted at warden.authenticate in case of a failed authentication and the user get redirected to the 'new' which is the sign_in page.

I just need to show the user a invalid_credentials tooltip/flash_message. So I did it by modifying :recall => "#{controller_path}#handle_create_fail" (look at auth_options) which calls handle_create_fails when authentication fails, inside which I setup the error messages.

I am not sure if I overlooked something that devise already provides.

How can I handle this better?

Rahul
  • 1,866
  • 17
  • 32

3 Answers3

3

'devise' stores error messages in rails 'flash', using flash[:notice] for success messages and flash[:alert] for problems.

Here's this from the devise documentation:

Remember that Devise uses flash messages to let users know if sign in was successful or failed. Devise expects your application to call "flash[:notice]" and "flash[:alert]" as appropriate.

This means that in your view file (or more generally in your application layout file) you should include something similar to these lines:

<%= content_tag(:div, flash[:error], :id => "flash_error") if flash[:error] %>
<%= content_tag(:div, flash[:notice], :id => "flash_notice") if flash[:notice] %>
<%= content_tag(:div, flash[:alert], :id => "flash_alert") if flash[:alert] %>

Here are some similar questions/answers:

Rails - Devise - Error messages when signing in?

Devise errors are displayed twice

devise - Customizing the User Edit Pages

Community
  • 1
  • 1
Kevin Bedell
  • 13,254
  • 10
  • 78
  • 114
0

I am not sure if I am understanding you correctly, but by simply placing 'alert' in your view (sign_in.html.erb), Devise will flash the error message.

<div class="alert">
  <%= alert %>
</div>
Yosep Kim
  • 2,931
  • 22
  • 23
0

I wanted to be able to do something similar, along the lines of form-specific error messaging like you might have on most Rails forms (as opposed to a layout-wide, global flash).

You can check out what I came up with in this Github gist: https://gist.github.com/3792471

Basically (notes below assume a devise scope of :user):

  • Add/use a custom FailureApp, used by devise+warden, which simply adds a "scoped" flash "indicator". That is, if devise+warden is exiting quickly due to a failed login and has, therefore, set the flash.now[:alert], add flash.now[:user] = [:alert]
  • Extend FormBuilder (actually, SimpleForm::FormBuilder in my gist, but should work with others) to add a #flash method, which checks for the scoped indicator(s). If found, the matches are extracted/deleted from the FlashHash and rendered. If not found (that is, flash[:alert] may or may not exist, but flash[:user] either does not exist or does not include :alert), do nothing so the flash remains available for the default use case.
  • Add rendering to relevant views/layouts.

Note that the layout in my example gist does not have conditional logic around the layout-rendered flash messages. I did that just do I could test to see what does and does not show up under various circumstances.

Corey Innis
  • 464
  • 4
  • 6