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())
}
}
defaultSuccessUrlis set to the desired UI screen.- I've already changed success handler to
SimpleUrlAuthenticationSuccessHandlerinstead ofSavedRequestAwareAuthenticationSuccessHandlerto turn off saving requested URL by Spring. successHandler.setUseReferer(false)to disableRefererheader 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
defaultSuccessUrlwill override yoursuccessHandler(), as setting the URL actually addsSavedRequestAwareAuthenticationSuccessHandlerthat you wanted to replace. Order matters, as there is only onesuccessHandlerin theoauth2Loginconfigurer.Instead, you will want to pass the
defaultSuccessUrlto the constructor ofSimpleUrlAuthenticationSuccessHandler, and only set thesuccessHandler(successHandler).