Spring Boot Security redirect after successful login - undefined
Solution 1
You can add a successHandler to redirect like this:
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
...
.formLogin()
.loginPage("/login")
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
redirectStrategy.sendRedirect(request, response, "/");
}
})
Solution 2
I had the same issue and this is a workaround that I used. First have a mapping for your root "/" that is unprotected
@RequestMapping(value = { "/" }, method = RequestMethod.GET)
public ModelAndView projectBase() {
return new ModelAndView("redirect:/home");
}
Have it redirect to where you want the user to go initially like home for example
@RequestMapping(value = { "/home" }, method = RequestMethod.GET)
public ModelAndView getHome() {
ModelAndView model = new ModelAndView("account/home");
model.addObject("user", userFacade.getJsonForUser(userFacade.getUserForClient()));
return model;
}
Make sure the root url is open in your security configuration like...
http.
authorizeRequests()
.antMatchers("/").permitAll()
What will happen is now it will hit the root /, and redirect to home which is restricted and send them to the loginpage with a return url of home. it will then write correctly as /home when they first login
For some reason spring security is not respecting the default success url, and it could be a configuration issue with your web server causing it. On my local machine I don't have this issue, but on some other machines I do. The workaround works in both places, since you always end up with a returnUrl.
Andrei Rînea
Orthodox Christian Passionated about software. Perfectionist, but still pragmatic. Security and Software Engineer. Application Security, .NET, Java and many other technologies
Updated on June 20, 2022Comments
-
Andrei Rînea almost 2 years
I have followed the spring boot security tutorial but the end result has an issue consisting in that after successful login the browser is redirect to
/undefined
.I have even cloned the code referenced in the tutorial, thinking I have typed something wrong, or forgot to add a component or something. No, the same issue is there.
Searching on Stackoverflow I found out that you need to define the default success URL in the
configure
method of theWebSecurityConfigurerAdapter
like so:.defaultSuccessUrl("/")
but still no go. Accessing a protected resource leads to the login page and upon successful login I don't get redirected to the protected resource. I get to the '/undefined' page. Forcing the success works, however:
.defaultSuccessUrl("/", true)
... but this is not what I would need because after successful login the user should be redirected to secured resource (initially) requested.
Here's the relevant parts of the project:
WebSecurityConfig:
package ro.rinea.andrei.Security; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/") .permitAll() .and() .logout() .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user").password("password").roles("USER"); } }
Controller:
package ro.rinea.andrei.Controllers; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class WebController { @RequestMapping("/") public String index() { return "index"; } @RequestMapping("/salut") public String salut() { return "salut"; } @RequestMapping("/login") public String login() { return "login"; } }
There are views defined for
index
,login
andsalut
(if needed I will add their contents)and the build.gradle file:
buildscript { ext { springBootVersion = '1.4.0.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'idea' apply plugin: 'spring-boot' jar { baseName = 'tstBut' version = '0.0.1-SNAPSHOT' } sourceCompatibility = 1.8 targetCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile('org.springframework.boot:spring-boot-devtools') compile('org.springframework.boot:spring-boot-starter-jdbc') compile('org.springframework.boot:spring-boot-starter-jersey') compile('org.springframework.boot:spring-boot-starter-mobile') compile('org.springframework.boot:spring-boot-starter-thymeleaf') compile('org.springframework.boot:spring-boot-starter-validation') compile('org.springframework.boot:spring-boot-starter-web') compile('org.springframework.boot:spring-boot-starter-web-services') compile('org.springframework.boot:spring-boot-starter-security') runtime('org.postgresql:postgresql') testCompile('org.springframework.boot:spring-boot-starter-test') testCompile('org.springframework.restdocs:spring-restdocs-mockmvc') }