I am using Spring Boot for the first time to setup a user login system for a REACT web-app. As of now I am trying to redirect the user to another page in my REACT-app after a successful authentication. I am using a custom AuthenticationSuccessHandler to handle the actual redirection.
@Override
protected void configure(HttpSecurity http) throws Exception {
CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(authenticationManagerBean());
customAuthenticationFilter.setFilterProcessesUrl("/api/v*/login/**");
http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers("/api/v*/login/**").permitAll();
http.authorizeRequests().antMatchers(HttpMethod.GET, "api/v*/users/**").hasAnyAuthority("PRODUCER");
http.authorizeRequests().antMatchers("/api/v*/registration/**").permitAll();
http.authorizeRequests().anyRequest().authenticated();
http.formLogin().loginPage("http://localhost:3000/login").successHandler(myAuthenticationSuccessHandler());
@Bean
public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){
return new RedirectLoginSuccessHandler();
}
public class RedirectLoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Authentication authentication) throws IOException {
httpServletResponse.sendRedirect("http://localhost:3000");
}
}
The API runs on port :8080 and the react login form runs on :3000/login, authentication is done by sending a POST-request to localhost:8080/api/v1/login (getting a JWT access token in return), after that is attempted I want the user to get redirected to the homepage at localhost:3000, but the redirect is being ignored unless I use the login form that you get from Spring with the loginForm() method.
I also tried sending a redirect along with the JWT token as a response to the POST-request to api/v1/login, but ran into problems with CORS doing that. What am I doing wrong here? The tutorials i've seen on redirecting after successful authentication refer to html files such as home.html to redirect, and I am assuming they are able to do this by having bundled together the REACT and Spring boot project into one mono-repository.
CodePudding user response:
Maybe try something like this ...
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
// ... endpoints
.formLogin()
... config
.defaultSuccessUrl("http://localhost:3000l", true)
// ... other configuration
}
}
CodePudding user response:
With formLogin
, Spring Security basically provides you these steps (simplified):
- When you call an API need to authenticate the user, if AccessDeniedException happens, a
AuthenticationEntryPoint
will redirect you toformLogin().loginPage("http://localhost:3000/login")
. - After the user fill out the
username
and thepassword
, you need to POST them toformLogin().loginProcessingUrl("/login123")
(default value if you don't specicify should be "/login"). - The
UsernamePasswordAuthenticationFilter
, after that, bases on the matcher on"/login123"
will intercept your POST, and validate your user withusername
andpassword
. - If they are validated successfully, your
.successHandler(myAuthenticationSuccessHandler())
will be called to do its job.
...
Here, because
authentication is done by sending a POST-request to localhost:8080/api/v1/login (getting a JWT access token in return)
You didn't follow the flow from step 2 (you didn't POST username/password to "/login123"), you couldn't get features supported by Spring Security after that (this.rememberMeServices.loginSuccess
, this.successHandler.onAuthenticationSuccess
,... for example).
For your case, after you get JWT from a POST-request to localhost:8080/api/v1/login
, you could redirect by yourself, you don't need to depend on .successHandler(myAuthenticationSuccessHandler())
.