springspring-bootkotlinspring-securityspring-kotlin

Spring Security OAuth 2.0 Google: redirect to default URL after unauthorized request instead of requested URL


I'm using Spring Security OAuth 2.0 with Google as identity provider. I have problem with proper handling of session timeout and reauthentication.

Scenario:

Current behaviour:

Desired behaviour:

My configuration class:

import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler

@Configuration
@EnableWebSecurity
class WebSecurityConfiguration: WebSecurityConfigurerAdapter() {

    @Value("\${app.security.oauth2.defaultSuccessUrl}")
    lateinit var defaultSuccessUrl: String

    @Throws(Exception::class)
    override fun configure(httpSecurity: HttpSecurity) {
        val successHandler = SimpleUrlAuthenticationSuccessHandler()
        successHandler.setUseReferer(false)
        httpSecurity
            .antMatcher("/**")
            .authorizeRequests()
            .antMatchers("/", "/login**", "/js/**", "/error**").permitAll()
            .anyRequest().authenticated()
            .and().oauth2Login()
            .successHandler(successHandler)
            .defaultSuccessUrl(defaultSuccessUrl)
            .and().logout().logoutSuccessUrl("/login").deleteCookies("JSESSIONID").permitAll()
            .and()
            .csrf().disable()
            .exceptionHandling()
            .authenticationEntryPoint(Http403ForbiddenEntryPoint())
    }

}

What I'm doing wrong?

Thanks in advance.

UPD: Updated code according to answer by Steve Riesenberg:

import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler

@Configuration
@EnableWebSecurity
class WebSecurityConfiguration: WebSecurityConfigurerAdapter() {

    @Value("\${app.security.oauth2.defaultSuccessUrl}")
    lateinit var defaultSuccessUrl: String

    @Throws(Exception::class)
    override fun configure(httpSecurity: HttpSecurity) {
        val successHandler = SimpleUrlAuthenticationSuccessHandler(defaultSuccessUrl)
        successHandler.setUseReferer(false)
        httpSecurity
            .antMatcher("/**")
            .authorizeRequests()
            .antMatchers("/", "/login**", "/js/**", "/error**").permitAll()
            .anyRequest().authenticated()
            .and().oauth2Login()
            .successHandler(successHandler)
            .and().logout().logoutSuccessUrl("/login").deleteCookies("JSESSIONID").permitAll()
            .and()
            .csrf().disable()
            .exceptionHandling()
            .authenticationEntryPoint(Http403ForbiddenEntryPoint())
    }

}

Solution

  • Setting the defaultSuccessUrl will override your successHandler(), as setting the URL actually adds SavedRequestAwareAuthenticationSuccessHandler that you wanted to replace. Order matters, as there is only one successHandler in the oauth2Login configurer.

    Instead, you will want to pass the defaultSuccessUrl to the constructor of SimpleUrlAuthenticationSuccessHandler, and only set the successHandler(successHandler).