Reputation: 371
I use Angular in the frontend and handle security with spring security in the backend.
However, Spring sec does not authenticate user. For both valid and not valid credential it's behavior is same. I want to catch "bad credential" for invalid user or password and user data for valid credential. What is my problem and how can I handle that? Thank you
spring security config
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public JdbcUserDetailsManager userDetailsManager(AuthenticationManager authenticationManager, DataSource dataSource) {
JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager();
userDetailsService.setDataSource(dataSource);
userDetailsService.setAuthenticationManager(authenticationManager);
return userDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/webjars/**", "/resources/**", "/js/**", "/public/**");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/login").permitAll().and()
.authorizeRequests().antMatchers("/index").permitAll().and()
.authorizeRequests().anyRequest().hasRole("USER").and()
.exceptionHandling()
.accessDeniedPage("/index?authorization_error=true")
.and()
.csrf()
.csrfTokenRepository(csrfTokenRepository())
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
.logout()
.logoutSuccessUrl("/index")
.logoutUrl("/logout.do")
.and()
.formLogin()
.usernameParameter("j_username")
.passwordParameter("j_password")
.failureUrl("/index?authentication_error=true")
.loginPage("/index")
.loginProcessingUrl("/j_security_check")
.and()
.sessionManagement().maximumSessions(1);
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
Angular controller:
var loginService = function () {
var deferred = $q.defer();
$http.post(contextPath + '/j_security_check', {j_username: $scope.credentials.j_username, j_password: $scope.credentials.j_password}).
success(function (data) {
deferred.resolve(data);
}).
error(function (data, status, header, config) {
$log.warn(data, status, header(), config);
deferred.reject(status);
});
return deferred.promise;
};
$scope.login = function () {
loginService().then(function (result) {
console.log(result);
$state.go('dashboard');
}, function (result) {
switch (result) {
case 401:
$scope.message = "Error " + result + ": username or password is not correct";
break;
case 403:
$scope.message = "Error " + result + ": username or password is not correct";
break;
default :
$scope.message = "Error " + result + " :unknown error";
}
})
};
Thank you
Upvotes: 0
Views: 548
Reputation: 1395
UPDATE:
Check this similar SO question which has example angularjs http interceptor getting directly csrf params and adding in the headers in all requests.
REASON for default angularJS doesn't work as mentioned in the link
By default AngularJS provides a mechanism to implement Cross Site Request Forgery, however this mechanism works with cookies only. Since Spring Security works by setting a token as an HTTP parameter, the out of the box solution AngularJS provides wouldn’t work.
As mentioned in the documentation of spring-security-csrf-token-interceptor project - "An AngularJS interceptor that sets the Spring Security CSRF token information in all HTTP requests" - it works by making a head call to receive the X-CSRF-TOKEN, it then stores this token and sends it out with every http request.
Summary : Add angular interceptor mentioned in the above project in yours to fix your case. Check the sample mentioned in that github project.
Upvotes: 2