Spring Boot Security redirect after successful login - undefined

17,744

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.

Share:
17,744
Andrei Rînea
Author by

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, 2022

Comments

  • Andrei Rînea
    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 the WebSecurityConfigurerAdapter 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 and salut (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')
    }