ruby-on-railsformsdevise

How can I get devise errors for a sign in form?


I'll preface this by saying that I have read the duplicate questions. They seem to be pretty old, and their solutions have not worked.

I have the following code for a custom sign in form in views/devise/sessions/new.html.erb:

<%= form_with model: resource, url: session_path(resource_name), as: resource_name do |form| %>
    <%= form.text_field :email, class: "input" %>
    <%= form.password_field :password, class: "input" %>
    <%= tag.button(class: "btn-gradient input-button", type: "submit") do %>
        <span>Sign In</span>
    <% end %>
<% end %>

I am trying to pull errors and display them, and the following does not work:

<% if resource.errors.any? %>
    <div class="error">
        <% resource.errors.full_messages.each do |message| %>
            - <%= message %></br>
        <% end %>
    </div>
<% end %>

I've tried a few other variants online, but it does not seem that any errors are caught. If I type an incorrect email password combination, nothing happens. I've used the same syntax in other forms (like creating or editing a model), and it works fine.

Not sure why it's different with a devise sign in.

How can I get errors in a devise form?


Solution

  • Your expectations are wrong.

    The speedrun explaination of how authentication in Devise works is that Devise::SessionsController#create calls self.resource = warden.authenticate!(auth_options) and if Warden cannot find a user with the given email/password it will throw(:warden). The throw is then caught by calling Devise::FailureApp which redirects the user to the sign in path.

    This is a more complex operation then your average scaffolded Rails controller that just renders the new view when the validations fail.

    There are no errors on the resource object because:

    You Ain't Gonna Need It.

    When Devise performs authentication fails it just sets a flash message which by default is "Invalid email or password.". Remember that flash messages are passed through a cookie from one request to the next - model instances are not.

    This is also the only feedback you should actually give. If you for example added a separate "Invalid email" message it lets an attacker performing a brute force attack determine if an email exists and you just made thier job a whole lot easier.

    You can customize the flash messages simply by defining your own locale file and if you want to you can display the flash messages on the form.