Photo by Markus Spiske on Unsplash
Spring boot - redirect to previous url on login w/ stateless application
When building any web application with secured resources, those urls would typically be protected by a login page. If a user tries to navigate to a secure url, the call would be intercepted and the user would be routed to login page. Post login, the user expects to land on the original url the user was trying to access.
Spring boot by provides multiple AuthenticationHandlers for supporting this functionality automatically. Typically SimpleUrlAuthenticationSuccessHandler or SavedRequestAwareAuthenticationSuccessHandler are used to build this functionality. However if your web application is Stateless, this doesn't work automatically. This is because Spring boot by default uses HttpSessionRequestCache to store the original secured url and use this stored attribute to redirect to in AuthenticationSuccessHandler. If your application is stateless and there is no persistent session, the previous url can't be logged up from HttpSessionRequestCache.
The solution is to leverage Cookies or any other mechanism to persist the old url which can persist between discrete http calls. Similar to HttpSessionRequestCache, Spring boot also provides CookieRequestCache which is backed by a Cookie.
Here is an example to use CookieRequestCache:
// WebSecurityConfig.java
@Autowired
private AuthenticationSuccessHandler authSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringRequestMatchers(request -> request.getHeader("X-Requested-With") != null).disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(publicPages).permitAll()
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login")
.successHandler(authSuccessHandler)
.permitAll()
.and().requestCache().requestCache(new CookieRequestCache())
.and().logout().permitAll()
}
This enables using CookieRequestCache and the original url is stored in REDIRECT_URI cookie.
The following is the snippet for leveraging this cookie during authentication process inside your custom AuthenticationSuccessHandler
@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
private AuthUtils authUtils;
private RequestCache requestCache = new CookieRequestCache();
@Autowired
public AuthenticationSuccessHandler(AuthUtils authUtils) {
this.authUtils = authUtils;
super.setRequestCache(requestCache);
super.setDefaultTargetUrl("/app");
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
//do whatever you need here specific to your auth success process
super.onAuthenticationSuccess(request, response, authentication);
}
}