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:
- Some request to REST API after session timeout.
- Frontend handles HTTP 403 and shows screen with link to Spring Security login endpoint.
- User clicks on this link. Spring issues redirect to Google login page with necessary parameters (code, state, etc.). User successfully reauthenticates.
Current behaviour:
- After login Google redirects to previously requested REST API URL. As a result user sees some JSON in browser. I simply don't understand what part of application could have been saved it. I disabled everything. (See comments below configuration class.)
Desired behaviour:
- After login Google redirects to some starting UI screen.
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())
}
}
defaultSuccessUrl
is set to the desired UI screen.- I've already changed success handler to
SimpleUrlAuthenticationSuccessHandler
instead ofSavedRequestAwareAuthenticationSuccessHandler
to turn off saving requested URL by Spring. successHandler.setUseReferer(false)
to disableReferer
header on HTTP level.- I'm using
Http403ForbiddenEntryPoint()
to just issue HTTP 403 on session timeout. Frontend handles this and shows login screen with link to Spring Security login URL.
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())
}
}
Setting the
defaultSuccessUrl
will override yoursuccessHandler()
, as setting the URL actually addsSavedRequestAwareAuthenticationSuccessHandler
that you wanted to replace. Order matters, as there is only onesuccessHandler
in theoauth2Login
configurer.Instead, you will want to pass the
defaultSuccessUrl
to the constructor ofSimpleUrlAuthenticationSuccessHandler
, and only set thesuccessHandler(successHandler)
.