title: Spring security login always lands in an error page with no message
body: <p>I'm using a login form for a small project in Spring but I have a small problem which is that every time I log in using a sign in form I get an error redirection.</p>
  
  <p>This is my SecurityConfiguration.java</p>
  
  <pre><code>package com.ffuentese;
  
  import javax.sql.DataSource;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.beans.factory.annotation.Value;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  import org.springframework.security.config.annotation.web.builders.WebSecurity;
  import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
  
  @Configuration
  @EnableWebSecurity
  public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  
      @Autowired
      private BCryptPasswordEncoder bCryptPasswordEncoder;
  
      @Autowired
      private DataSource dataSource;
  
      @Value("${spring.queries.users-query}")
      private String usersQuery;
  
      @Value("${spring.queries.roles-query}")
      private String rolesQuery;
  
      @Override
      protected void configure(AuthenticationManagerBuilder auth)
              throws Exception {
          auth.
              jdbcAuthentication()
                  .usersByUsernameQuery(usersQuery)
                  .authoritiesByUsernameQuery(rolesQuery)
                  .dataSource(dataSource)
                  .passwordEncoder(bCryptPasswordEncoder);
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
  
          http.
              authorizeRequests()
                  .antMatchers("/").permitAll()
                  .antMatchers("/login").permitAll()
                  .antMatchers("/registration").permitAll()
                  .antMatchers("/**").hasAuthority("ADMIN").anyRequest()
                  .authenticated().and().csrf().disable().formLogin()
                  .loginPage("/login").failureUrl("/login?error=true")
                  .defaultSuccessUrl("/home")
                  .usernameParameter("email")
                  .passwordParameter("password")
                  .and().logout()
                  .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                  .logoutSuccessUrl("/").and().exceptionHandling()
                  .accessDeniedPage("/access-denied");
      }
  
      @Override
      public void configure(WebSecurity web) throws Exception {
          web
             .ignoring()
             .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
      }
  
  }
  </code></pre>
  
  <p>My sign in form:</p>
  
  <pre><code>&lt;form th:action="@{/login}" method="POST" class="form-signin"&gt;
      &lt;h3 class="form-signin-heading" th:text="Welcome"&gt;&lt;/h3&gt;
      &lt;br/&gt;
  
      &lt;input type="text" id="email" name="email"  th:placeholder="Email"
          class="form-control" /&gt; &lt;br/&gt; 
      &lt;input type="password"  th:placeholder="Password"
          id="password" name="password" class="form-control" /&gt; &lt;br /&gt; 
  
      &lt;div align="center" th:if="${param.error}"&gt;
          &lt;p style="font-size: 20; color: #FF1C19;"&gt;Email or contraseña errónea, por favor intente nuevamente.&lt;/p&gt;
      &lt;/div&gt;
      &lt;button class="btn btn-lg btn-primary btn-block" name="Submit" value="Login" type="Submit" th:text="Login"&gt;&lt;/button&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>My loginController.java</p>
  
  <pre><code>package com.ffuentese;
  
  import javax.validation.Valid;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.security.core.Authentication;
  import org.springframework.security.core.context.SecurityContextHolder;
  import org.springframework.stereotype.Controller;
  import org.springframework.validation.BindingResult;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RequestMethod;
  import org.springframework.web.servlet.ModelAndView;
  
  import com.ffuentese.User;
  
  @Controller
  public class LoginController {
  
      @Autowired
      private UserService userService;
  
      @RequestMapping(value={"/", "/login"}, method = RequestMethod.GET)
      public ModelAndView login(){
          ModelAndView modelAndView = new ModelAndView();
          modelAndView.setViewName("login");
          return modelAndView;
      }
  
      @RequestMapping(value="/home", method = RequestMethod.GET)
      public ModelAndView homeV(){
          ModelAndView modelAndView = new ModelAndView();
          Authentication auth = SecurityContextHolder.getContext().getAuthentication();
          modelAndView.setViewName("home");
          return modelAndView;
      }
  
  
      @RequestMapping(value="/registration", method = RequestMethod.GET)
      public ModelAndView registration(){
          ModelAndView modelAndView = new ModelAndView();
          User user = new User();
          modelAndView.addObject("user", user);
          modelAndView.setViewName("registration");
          return modelAndView;
      }
  
      @RequestMapping(value = "/registration", method = RequestMethod.POST)
      public ModelAndView createNewUser(@Valid User user, BindingResult bindingResult) {
          ModelAndView modelAndView = new ModelAndView();
          User userExists = userService.findUserByEmail(user.getEmail());
          if (userExists != null) {
              bindingResult
                      .rejectValue("email", "error.user",
                              "There is already a user registered with the email provided");
          }
          if (bindingResult.hasErrors()) {
              modelAndView.setViewName("registration");
          } else {
              userService.saveUser(user);
              modelAndView.addObject("successMessage", "User has been registered successfully");
              modelAndView.addObject("user", new User());
              modelAndView.setViewName("registration");
  
          }
          return modelAndView;
      }
  
      @RequestMapping(value="/admin/home", method = RequestMethod.GET)
      public ModelAndView home(){
          ModelAndView modelAndView = new ModelAndView();
          Authentication auth = SecurityContextHolder.getContext().getAuthentication();
          User user = userService.findUserByEmail(auth.getName());
          modelAndView.addObject("userName", "Welcome " + user.getName() + " " + user.getLastName() + " (" + user.getEmail() + ")");
          modelAndView.addObject("adminMessage","Content Available Only for Users with Admin Role");
          modelAndView.setViewName("admin/home");
          return modelAndView;
      }
  
  
  }
  </code></pre>
  
  <p>So, instead of going from login to /home it ends up landing in /error. The error itself is a line of code like this:</p>
  
  <blockquote>
    <p>{"timestamp":"2018-04-04T21:28:28.944+0000","status":999,"error":"None","message":"No
    message available"}</p>
  </blockquote>
  
  <p>The form does work because if I move from /error and go to any protected URL they can be opened. </p>
  
  <p>EDIT: The original code comes from this repository and I adapted it to my own project <a href="https://github.com/gustavoponce7/SpringSecurityLoginTutorial" rel="noreferrer">https://github.com/gustavoponce7/SpringSecurityLoginTutorial</a> also explained <a href="https://medium.com/@gustavo.ponce.ch/spring-boot-spring-mvc-spring-security-mysql-a5d8545d837d" rel="noreferrer">here</a> </p>
  
  <p>EDit: Another point I think it's important is that if I login and then login again the form seems to work alright taking the user from login to /home as expected. It's odd.</p>