title: Spring Boot Security Authentication - 302 Redirects
body: <p>I am trying to test my web api thats secured using the standard Spring Security API.  I have implemented my own User authentication service by implementing UserDetailService.  However whenever I login to my application the /login api keeps returning a 302 redirect.  I verified that my login page is working correctly by manually testing both good credentials and bad credentials and it did properly authenticate correctly to the homepage depending on whether the credentials were good, however it still returned a 302 for /login.  Im wondering why Spring/Thymeleaf is returning a 302 redirect when performing the /login request.  This is preventing my ability to test any of my guarded endpoints when locked down with spring security.</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(securedEnabled = true)
  public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  private UserDetailsService userDetailsService;
  
  @Bean
  public BCryptPasswordEncoder bCryptPasswordEncoder() {
      return new BCryptPasswordEncoder();
  }
  
  @Bean
  public JwtTokenFilter jwtTokenFilter() {
      return new JwtTokenFilter();
  }
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
  
      http
              .csrf()
              .disable()
              .cors()
              .and()
              .authorizeRequests().antMatchers("/profiles/**","/img/**","/resources","/v2/**","/users", "/login", "/error/**", "/keepalive", "/register").permitAll()
              .anyRequest().authenticated()
              .and()
              .formLogin()
              .loginPage("/login").permitAll()
              .defaultSuccessUrl("/")
              .permitAll()
              .and()
              .logout();
  
      http.addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
  }
  
  @Bean
  public CorsConfigurationSource corsConfigurationSource() {
      final CorsConfiguration configuration = new CorsConfiguration();
      configuration.setAllowedOrigins(asList("*"));
      configuration.setAllowedMethods(asList("HEAD",
              "GET", "POST", "PUT", "DELETE", "PATCH"));
      // setAllowCredentials(true) is important, otherwise:
      // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
      configuration.setAllowCredentials(true);
      // setAllowedHeaders is important! Without it, OPTIONS preflight request
      // will fail with 403 Invalid CORS request
      configuration.setAllowedHeaders(asList("Authorization", "Cache-Control", "Content-Type"));
      final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      source.registerCorsConfiguration("/**", configuration);
      return source;
  }
  
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
  }
  </code></pre>
  
  <p>Login.html Page</p>
  
  <pre><code>   &lt;!DOCTYPE html&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
  &gt;
  &lt;head&gt;
      &lt;title&gt;Login&lt;/title&gt;
      &lt;div th:replace="fragments/header :: header-css"/&gt;
  &lt;/head&gt;
  &lt;body class="white-bg"&gt;
  
  &lt;div th:replace="fragments/header :: header"/&gt;
  
      &lt;div class="middle-box text-center loginscreen"&gt;
          &lt;div&gt;
              &lt;div&gt;
  
                  &lt;h1 class="logo-name"&gt;&lt;/h1&gt;
  
              &lt;/div&gt;
          &lt;h3&gt;Welcome to &lt;/h3&gt;
  
          &lt;p&gt;Login in. To see it in action.&lt;/p&gt;
          &lt;form th:action="@{/login}" method="post"&gt;
              &lt;fieldset&gt;
                  &lt;div th:if="${param.error}"&gt;
                      &lt;div class="alert alert-danger"&gt;
                          Invalid username and password.
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div th:if="${param.logout}"&gt;
                      &lt;div class="alert alert-info"&gt;
                          You have been logged out.
                      &lt;/div&gt;
                  &lt;/div&gt;
  
                  &lt;div class="form-group"&gt;
                      &lt;input type="text" name="username" id="username" class="form-control"
                             placeholder="UserName" required="true" autofocus="true"/&gt;
                  &lt;/div&gt;
                  &lt;div class="form-group"&gt;
                      &lt;input type="password" name="password" id="password" class="form-control"
                             placeholder="Password" required="true"/&gt;
                  &lt;/div&gt;
                  &lt;input type="submit" class="btn btn-lg btn-primary btn-block" value="Sign In"/&gt;
  
                  &lt;a href="#"&gt;&lt;small&gt;Forgot password?&lt;/small&gt;&lt;/a&gt;
                  &lt;p class="text-muted text-center"&gt;&lt;small&gt;Do not have an account?&lt;/small&gt;&lt;/p&gt;
                  &lt;a class="btn btn-sm btn-white btn-block" href="register.html"&gt;Create an account&lt;/a&gt;
              &lt;/fieldset&gt;
          &lt;/form&gt;
          &lt;p class="m-t"&gt; &lt;small&gt;DigiProof Company &amp;copy; 2017&lt;/small&gt; &lt;/p&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p></p>
  
  <p>
  </p>
  
  <p>BaseController.java for routing</p>
  
  <pre><code>@Controller
  public class BaseController {
  
      @Autowired
      private UserService userService;
  
      @GetMapping("/")
      public String homeMain() {
          return "home";
      }
  
      @GetMapping("/home")
      public String home() {
          return "home";
      }
  
      @GetMapping("/login")
      public String login(Principal principal) {
          if (principal!=null &amp;&amp; ((Authentication)principal).isAuthenticated())
              return "redirect:/home";
          else
              return "login";
      }
  
      @RequestMapping(value="/registration", method = RequestMethod.GET)
      public ModelAndView registration(){
          ModelAndView modelAndView = new ModelAndView();
          User user = new User();
          modelAndView.addObject("user", user);
          modelAndView.setViewName("register");
          return modelAndView;
      }
  
      @RequestMapping(value = "/registration", method = RequestMethod.POST)
      public ModelAndView createNewUser(@Valid User user, BindingResult bindingResult) {
          ModelAndView modelAndView = new ModelAndView();
          User userByEmailExists = userService.findUserByEmail(user.getEmail());
          if (userByEmailExists != null) {
              bindingResult
                      .rejectValue("email", "error.user",
                              "There is already a user registered with the email provided");
          }
          if (bindingResult.hasErrors()) {
              modelAndView.setViewName("register");
          } else {
              userService.save(user);
              modelAndView.addObject("successMessage", "User has been registered successfully");
              modelAndView.addObject("user", new User());
              modelAndView.setViewName("register");
          }
          return modelAndView;
      }
  
      @GetMapping("/profile")
      public String profile() {
          return "profile";
      }
  
      @GetMapping("/activity")
      public String activity() {
          return "activity";
      }
  
      @GetMapping("/teams")
      public String teams() {
          return "teams";
      }
  
      @GetMapping("/404")
      public String error404() {
          return "/error/403";
      }
  
      @GetMapping("/403")
      public String error403() {
          return "/error/403";
      }
  
      @GetMapping("/500")
      public String error500() {
          return "/error/500";
      }
  
      @GetMapping("/error")
      public String error() {
          return "/error/500";
      }
  
  
  }
  </code></pre>