title: Spring MVC, Spring Security: Unable to load login template
body: <p>When to access any route, I get redirected to my login page, including accessing my login page, which is expected. Now the problem is the login page does not even load. I have configured the controller method, hander, template configuration, and security configuration necessary to make this work, but all I get is the error below:</p>
  
  <p><a href="http://localhost:8080/login?errorMessage=Login+to+use+the+app" rel="nofollow noreferrer">http://localhost:8080/login?errorMessage=Login+to+use+the+app</a></p>
  
  <p><a href="https://i.stack.imgur.com/vWAQv.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vWAQv.png" alt="enter image description here"></a></p>
  
  <p><strong>UserController.java</strong></p>
  
  <pre><code>@Controller
  public class UserController {
      @Autowired
      private UserService userService;
  
      @GetMapping("/signup")
      public String signup(Model model) {
          model.addAttribute("user", new User());
          return "signup";
      }
  
      @PostMapping("/users")
      public String createUser(User user) {
          // only create user if it does not exist
          if (userService.findByUsername(user.getUsername()) == null) {
              user.setRoles(new String[] {"ROLE_USER"});
              userService.save(user);
              return "redirect:/login";
          }
          else {
              return "redirect:/signup";
          }
      }
  
      @GetMapping("/login")
      public String login(Model model) {
          model.addAttribute("user", new User());
          return "login";
      }
  
      @GetMapping("/profile")
      public String currentUserProfile(Model model) {
          User currentUser = (User) model.asMap().get("currentUser");
          model.addAttribute("user", currentUser);
          model.addAttribute("authorized", true);
          return "profile";
      }
  
      @GetMapping("/users/{id}")
      public String userProfile(@PathVariable Long id, Model model) {
          User queriedUser = userService.findOne(id);
          model.addAttribute("user", queriedUser);
  
          User currentUser = (User) model.asMap().get("currentUser");
          if (currentUser != null &amp;&amp; currentUser.isAdmin()) {
              model.addAttribute("authorized", true);
          }
  
          return "profile";
      }
  }
  </code></pre>
  
  <p><strong>UserHandler.java</strong></p>
  
  <pre><code>@ControllerAdvice(basePackages = "com.valencra.recipes.web.controller")
  public class UserHandler {
      public static final String USERNAME_NOT_FOUND_ERR_MSG = "Unable to find username";
      public static final String ACCESS_DENIED_ERR_MSG = "Login to use the app";
  
      @Autowired
      private UserService userService;
  
      @ModelAttribute("authenticatedUser")
      public User addAuthenticatedUser() {
          final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  
          if (authentication != null) {
              String username = authentication.getName();
              User user = userService.findByUsername(username);
              if (user != null) {
                  return user;
              }
              else {
                  throw new UsernameNotFoundException(USERNAME_NOT_FOUND_ERR_MSG);
              }
          }
          else {
              throw new AccessDeniedException(ACCESS_DENIED_ERR_MSG);
          }
      }
  
      @ExceptionHandler(AccessDeniedException.class)
      public String redirectIfUserNotAuthenticated(RedirectAttributes redirectAttributes) {
          redirectAttributes.addAttribute("errorMessage", ACCESS_DENIED_ERR_MSG);
      return "redirect:/login";
      }
  
      @ExceptionHandler(UsernameNotFoundException.class)
      public String redirectIfUserNotFound(RedirectAttributes redirectAttributes) {
          redirectAttributes.addAttribute("errorMessage", USERNAME_NOT_FOUND_ERR_MSG);
          return "redirect:/login";
      }
  }
  </code></pre>
  
  <p><strong>TemplateConfig.java</strong></p>
  
  <pre><code>@Configuration
  public class TemplateConfig {
      @Bean
      public SpringResourceTemplateResolver templateResolver() {
          final SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
          templateResolver.setPrefix("classpath:/templates/");
          templateResolver.setSuffix(".html");
          templateResolver.setTemplateMode("LEGACYHTML5");
          return templateResolver;
      }
  
      @Bean
      public SpringTemplateEngine templateEngine() {
          final SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
          springTemplateEngine.addTemplateResolver(templateResolver());
          springTemplateEngine.addDialect(new SpringSecurityDialect());
          return springTemplateEngine;
      }
  
      @Bean
      public ThymeleafViewResolver viewResolver() {
          final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
          viewResolver.setTemplateEngine(templateEngine());
          viewResolver.setOrder(1);
          return viewResolver;
      }
  }
  </code></pre>
  
  <p><strong>SecurityConfig.java</strong></p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
      @Autowired
      private RecipesAppUserDetailsService recipesAppUserDetailsService;
  
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(recipesAppUserDetailsService)
              .passwordEncoder(User.PASSWORD_ENCODER);
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http
            .authorizeRequests()
            .antMatchers("/signup").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .successHandler(loginSuccessHandler())
            .failureHandler(loginFailureHandler())
            .and()
            .logout()
            .permitAll()
            .logoutSuccessUrl("/login")
            .and()
            .csrf().disable();
  
          http.headers().frameOptions().disable();
      }
  
      public AuthenticationSuccessHandler loginSuccessHandler() {
          return (request, response, authentication) -&gt; response.sendRedirect("/");
      }
  
      public AuthenticationFailureHandler loginFailureHandler() {
          return (request, response, exception) -&gt;       
          response.sendRedirect("/login");
      }
  
      @Bean
      public EvaluationContextExtension securityExtension() {
          return new EvaluationContextExtensionSupport() {
              @Override
              public String getExtensionId() {
                  return "security";
              }
  
               @Override
               public Object getRootObject() {
                   Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                  return new SecurityExpressionRoot(authentication) {};
              }
          };
      }
  }
  </code></pre>
  
  <p><strong>application.properties</strong></p>
  
  <pre><code># Package where our entities (models) are located
  recipes.entity.package = com.valencra.recipes.model
  
  # Details for our datasource
  recipes.db.driver = org.h2.Driver
  recipes.db.url = jdbc:h2:mem:recipes
  
  # Hibernate properties
  hibernate.dialect = org.hibernate.dialect.H2Dialect
  hibernate.implicit_naming_strategy = org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
  hibernate.format_sql = true
  hibernate.show_sql = true
  hibernate.hbm2ddl.auto = create-drop
  
  spring.data.rest.basePath=/api/v1
  </code></pre>
  
  <p><strong>resources directory</strong></p>
  
  <p><a href="https://i.stack.imgur.com/U7GTN.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/U7GTN.png" alt="enter image description here"></a></p>
  
  <p><strong>EDIT</strong>: See @lgaleazzi's answer, and the comments that follow. Essentially, removing the UserHandler class fixes it.</p>