GCarbajosa
GCarbajosa

Reputation: 246

Spring security returns 302 when trying to logout

I use Spring security (4.0.2.RELEASE) to secure my app.

I can login just fine and my authenticated URLs are protected, but when I try to logout I constantly get 302 POST responses followed by a redirect to my configured failureUrl ("/cms/login?error").

Here's my WebSecurityConfig class

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
   @Override
   protected void configure(HttpSecurity http) throws Exception
   {        
       http        
       .authorizeRequests()
           .antMatchers("/*").permitAll()
           .antMatchers("/cms/*").authenticated()
           .antMatchers("/cms/*/*").authenticated()
           .antMatchers("/cms/*/*/*").authenticated().and()
       .formLogin()
           .loginPage("/cms/login")
           .defaultSuccessUrl("/cms/login?success")
           .failureUrl("/cms/login?error")
           .permitAll().and()
       .logout()
           .logoutUrl("/cms/login?logout")
           .logoutSuccessUrl("/cms/login")
           .permitAll();
   }

   @Autowired
   public void configureGlobal(AuthenticationManagerBuilder auth)      throws Exception
   {
       auth.inMemoryAuthentication()
           .withUser("u")
           .password("p")
           .roles("USER");
   }

   @Bean
   public PasswordEncoder passwordEncoder()
   {
       return new BCryptPasswordEncoder();
   }
  }

Here's my login controller:

@Slf4j
@Controller
@RequestMapping(value = {"/cms", "/cms/login"})
public class CmsLoginController extends CmsBaseController
{   
    @RequestMapping
    public ModelAndView handleLogin(HttpServletResponse request,
                                    Model model,
                                    @RequestParam(value = LOGIN_SUCCESS, required = false) String success,
                                    @RequestParam(value = LOGIN_ERROR, required = false) String error,
                                    @RequestParam(value = LOGOUT, required = false) String logout)
    {   
        try
        {       
            if (success != null)
            {               
                setLoggedIn(true);
                request.sendRedirect(XXXXX);
            }

            if (error != null)
            {
                model.addAttribute(LOGIN_ERROR, "Invalid username and password!");
            }

            if (logout != null)
            {
                model.addAttribute(LOGOUT, "You've been logged out successfully.");
                setLoggedIn(false);
            }

            return new ModelAndView(CMS_CONTEXT + LOGIN_URL);
        }
        catch(Exception e)
        {
            setLoggedIn(false);
            log.error(e.toString(), e);

            return new ModelAndView(ERROR_VIEW_NAME);
        }   
    }
}    

For the record, I initially got the logout functionality working fine, but I must have introduced some change that has broken it unfortunately...

Any thoughts? Thank you

Upvotes: 5

Views: 4784

Answers (2)

BJ5
BJ5

Reputation: 512

Unnecessary Logout logic done by spring for redirection Bothers me a little.

The default behavior should have been straight forward instead of the redirect, and they could have kept a provision for special cases.

Use the below in configure method

.logout().logoutUrl("/api/logout")
            .logoutSuccessHandler(new LogoutSuccessHandler() {

                @Override
                public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
                        Authentication authentication) throws IOException, ServletException {
                    System.out.println("success");
                }
            });

Credits to this link https://www.codeproject.com/Tips/521847/Logout-Spring-s-LogoutFilter

Upvotes: 2

Selindek
Selindek

Reputation: 3423

I think the problem is the CSRF filter. In Spring Security 4 the CSRF prevention is turned on by default, do each POST request needs a CSRF token.

If you migrated your code from a previous Spring version then there is a very good chance that this is the problem.

For a quick test add http.csrf().disable to your configuration. If it works that way then turn back the CSRF protection and add the CSRF token somehow into your POST logout request.

Upvotes: 0

Related Questions