uncallable
uncallable

Reputation: 301

Spring security - Disable logout redirect

I'm using spring security with REST, and I'm using the URL (/logout) as an endpoint for my logout method. But after calling this method, it redirect me to (/login?logout), I know this is the spring logOutSuccessUrl. And I want to get rid of the redirection. This is my code:

protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
         .antMatchers("/login").permitAll()
         .anyRequest().fullyAuthenticated()
         .and().requiresChannel().anyRequest().requiresSecure()
         .and().httpBasic().disable().logout()
         .disable()
       //  .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK))
          .csrf().disable();

}

I tried to use HttpStatusReturningLogoutSuccessHandler but it didn't work, and even setting logoutSuccessUrl() doesn't change anything.

Do you know how can I disable this redirection?

Upvotes: 30

Views: 25117

Answers (10)

sge
sge

Reputation: 718

In spring security 6.x if you want to have csrf only for some endpoints and your are doing the login/logout by your self, you can define it like that:

  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
        .csrf(csrf -> csrf.ignoringRequestMatchers("/login",
                                                   "/logout",
                                                   "/instances",
                                                   "/instances/*",
                                                   "/actuator/**"))
        .httpBasic(AbstractHttpConfigurer::disable)
        .formLogin(AbstractHttpConfigurer::disable)
        .logout(AbstractHttpConfigurer::disable)
        .build();
  }

Upvotes: 0

sovanrothaa
sovanrothaa

Reputation: 1042

(Kotlin) On Spring security 6, You can just disable it like this:

@Configuration
class SecurityConfig(
    private val jwtAuthFilter: JwtAuthFilter,
    private val authenticationProvider: AuthenticationProvider
) {

    @Bean
    @Throws(Exception::class)
    fun securityFilterChain(http: HttpSecurity): SecurityFilterChain? {
        return http
            .csrf { it.disable() }
            .cors(Customizer.withDefaults())
            .authorizeHttpRequests {
                it.requestMatchers("/auth/**", "/api-docs/**", "swagger-ui/**")
                    .permitAll()
                    .anyRequest()
                    .authenticated()
            }
            .sessionManagement { session ->
                session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            }
            .formLogin { it.disable()} // <-- Disable form login
            .logout { it.disable() } // <-- Disable logout redirect
            .authenticationProvider(authenticationProvider)
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter::class.java)
            .build()
    }
}

Upvotes: 0

edigu
edigu

Reputation: 10099

As of 2022, none of the answers above worked for me for different reasons (Using Spring Boot 2.6.6 + Thymeleaf).

Simplest solution that worked for me was implementing a POST form with a valid CSRF token in it. And rest of the default login/logout implementation provided by spring security just works out of the box.

So my web security config uses bare-bone defaults provided by spring-boot:

protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/resources/**").permitAll()
        .anyRequest()
        .fullyAuthenticated()
        .and().formLogin();
    }

and my template looks like (using BS5 dropdowns):

<ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#">Settings</a></li>
    <li><a class="dropdown-item" href="#">Profile</a></li>
    <li>
        <form action="/logout" method="POST">
            <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
            <button class="dropdown-item" type="submit">Sign out</button>
        </form>
    </li>
</ul>

Please DON'T sacrifice the security (unless you have a valid reason for it) by disabling the CSRF token validation http.csrf().disable() just to be able to make GET /logout work without redirects, as recommended as solution by many neglectful articles around the web.

Upvotes: 1

Aura
Aura

Reputation: 780

for logoutSuccessXXX() action, do not forget to add permitAll() since the cookie is cleared after the logout() method is called. So my sample solution is:

http
   ......
   .and()
       .logout()
           .logoutUrl("/logout")
           .logoutSuccessUrl("/logoutSuccess")
           **.permitAll()**

Upvotes: 1

Kathryn Newbould
Kathryn Newbould

Reputation: 63

I used this:

    @ResponseStatus(HttpStatus.NO_CONTENT)
@PostMapping(value = "/oauth/revoke")
public void revokeToken(Authentication authentication) {
    ofNullable(authentication).ifPresent(auth -> {
        OAuth2AccessToken accessToken = tokenStore.getAccessToken((OAuth2Authentication) auth);

        ofNullable(accessToken).ifPresent(oAuth2AccessToken -> {
            ofNullable(oAuth2AccessToken.getRefreshToken()).ifPresent(tokenStore::removeRefreshToken);
            tokenStore.removeAccessToken(accessToken);
        });
    });
}

From this gist

Which worked perfectly. I recommend doing this over the logout() override primarily because it (well, it works, but other than that) preserves the oauth2 basic flow (/oauth/revoke) instead of using /logout or similar.

Hope that helps!

Upvotes: 0

Younes
Younes

Reputation: 1671

Foo those who use XML config, here is the equivalent snippet for the one given by Tahir Akhtar.

Within <http> element, configure the <logout> element as follows:

<logout
    logout-url          = "/some/path/for/logout"
    invalidate-session  = "true"
    delete-cookies      = "JSESSIONID"
    success-handler-ref = "httpStatusReturningLogoutSuccessHandler"
/>

And define httpStatusReturningLogoutSuccessHandler bean as follows:

<bean
    id      = "httpStatusReturningLogoutSuccessHandler"
    class   = "org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler"
/>

Upvotes: 3

Sebastian
Sebastian

Reputation: 868

So since there is no accepted answer yet, i post my solution, which worked for me:

.logout()
.logoutUrl("/api/user/logout")
.permitAll()
.logoutSuccessHandler((httpServletRequest, httpServletResponse, authentication) -> {
    httpServletResponse.setStatus(HttpServletResponse.SC_OK);
})
.and()

Just return a clean HTTP_OK (200) after successful logout - spring won't redirect you in this case

Upvotes: 28

user3888170
user3888170

Reputation: 11

You might want to try this

http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/thisistomisleadlogoutfilter"));

This effectively redirects /thisistomisleadlogoutfilter to login?logout. As such you should be able to use /logout instead

Upvotes: 1

Tahir Akhtar
Tahir Akhtar

Reputation: 11625

Following code works for me (notice that it doesn't have logout().disable())

http.logout().permitAll();
http.logout().logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)));

Upvotes: 53

Ahmad
Ahmad

Reputation: 1474

Use this method:

.logout().logoutSuccessUrl("enter address here where you want to go after logout")

Upvotes: 2

Related Questions