0

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

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

thank you it really help me. now I can login. but I need my user data such as his role how can I send these data instead of just 'ok' in response
do you mean after login you need user role in response ? i dont see in your code where you are granting ROLE_USER to the logged in user.
yes, your`re right but if I want to access user data such as name,email ,... how can I handle that
As you are using spring formLogin(), you can access username in your JSP as ${pageContext.request.userPrincipal.name} but email you need to expose or set somewhere in your request session and use it like <%=request.getSession().getAttribute("email")%>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.