I'm trying to create a javascript application communicating with the backend written with spring (spring-boot) only through the rest interface (@RestController). The problem is that the request is cross domain and in the end the session doesn't seem to be established after the user logs into the application. When I try to send a new http request to the backend, after logging in, the Principal is empty.
Here's my security configuration:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**").permitAll()
.and()
.formLogin()
.passwordParameter("password")
.usernameParameter("email")
.loginPage("/")
.failureHandler(new JsonAuthenticationFailureHandler())
.successHandler(new JsonAuthenticationSuccessHandler())
.and()
.rememberMe()
.and()
.logout()
.deleteCookies("remember-me")
.logoutSuccessUrl("/")
.logoutUrl("/logout")
.and()
.csrf()
.disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, PasswordEncoder encoder) throws Exception {
auth.userDetailsService(userService).passwordEncoder(encoder);
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
Here's my CORS configuration:
@Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
And an example controller that I try to call after successful login:
@RestController
@RequestMapping("/rest/users")
public class UserController extends AbstractRestController {
@Autowired
private UserService userService;
/**
* Exposed public method for registering the user
*
* @param email email to log in
* @param password password to log in
* @return BooleanResponse.result == true if the user registration succeeded without any problems
*/
@RequestMapping(value = "/register", method = {RequestMethod.POST, RequestMethod.GET})
public RegistrationResponse register(@RequestParam String email, @RequestParam String password) {
try {
userService.createUser(email, password);
} catch (UserRegistrationException e) {
return new RegistrationResponse(e.getErrors());
}
return new RegistrationResponse(Arrays.asList(RegistrationStatus.SUCCESS));
}
/**
* Determines whether a user with a specific email address already exists
*
* @param email email address to be searched for
* @return BooleanResponse.result = true if the user with the specific email already exists
*/
@RequestMapping(value = "/userExists", method = {RequestMethod.POST, RequestMethod.GET})
public BooleanResponse userExists(@RequestParam String email) {
boolean response = userService.userWithEmailExists(email);
return new BooleanResponse(response);
}
/**
* Searches for the user info
*
* @param principal uniquely identifying the logged in user
* @return user info for the user with the specified email address
*/
@RequestMapping(value = "/userInfo", method = RequestMethod.GET)
public UserInfo getUserInfo(Principal principal) {
return userService.findUserInfo(principal.getName());
}
/**
* Update info of the currently logged in user
*
* @param userInfo new user info provided in the request body
*/
@RequestMapping(value = "/userInfo", method = RequestMethod.POST)
public void submitUserInfo(@RequestBody UserInfo userInfo, Principal principal) {
userService.updateUserInfo(principal.getName(), userInfo);
}
}
so submitUserInfo and getUserInfo should receive the Principal object if the user is logged in, but they don't. I also tried to add session attributes in JsonAuthenticationSuccessHandler, but when I add the appropriate @SessionAttributes to my controller and try to get the attributes inside the method with @ModelAttribute, I still cannot get it, hence the assumption that my http session was not properly established.