0

I have an application that will be deployed at two places. There would be one master and one slave. I have a requirement that some of the requests should be satisfied by slave and others by master.

For this, I am sending login request to master on successful login to slave. I am able to achieve this.

My problem is, when i try to access any resource from master(request a resource from master originating from slave) after logging in, It is giving unauthorized(401) error.

Login controller:

  $http.post('j_spring_security_check', payload, config).success(function(data, textStatus, jqXHR, dataType) {
                    if ($scope.rememberme) {
                        var user = {
                            username: $scope.username,
                            password: $rootScope.encryptPass($scope.password, true),
                            rememberme: $scope.rememberme
                        };
                        localStorage.setItem('user', JSON.stringify(user));
                    } else {
                        localStorage.removeItem('user');
                    }
                    $rootScope.pingServer();
                    $rootScope.retrieveNotificationCount();
                    $http.post('http://localhost:9090/context/j_spring_security_check',payload, config).success(function(data, textStatus, jqXHR, dataType) {

                        $rootScope.pingServer();
                    }).error(function(data, status, headers, config) {

                    });
                });

app.js

rootapp.config(['$httpProvider', function(httpProvider) {
            httpProvider.interceptors.push(['$rootScope', function($rootScope) {
                    return {
                        request: function(config) {
                            config.headers = config.headers||{};
                            config.headers['withCredentials'] = true;
                            config.headers['useXDomain'] = true;
                            return config;
                        }
                    }
                }]);

My server has a filter

@Singleton
public class ResponseCorsFilter implements Filter {
 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if (servletResponse instanceof HttpServletResponse) {
            if (request.getMethod().equals("OPTION") || request.getMethod().equals("OPTIONS")) {
                System.out.println("In Options");
                if (request.getServletPath().equals("/j_spring_security_check")) {
                    System.out.println("request path match");
                    alteredResponse.setStatus(HttpServletResponse.SC_OK);
                    addHeadersFor200Response(alteredResponse);
                    return;
                }
            }

            addHeadersFor200Response(alteredResponse);
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    private void addHeadersFor200Response(HttpServletResponse response) {
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Credentials", "true");
        response.addHeader("Access-Control-Allow-Methods", "ACL, CANCELUPLOAD, CHECKIN, CHECKOUT, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, SEARCH, UNCHECKOUT, UNLOCK, UPDATE, VERSION-CONTROL");
        response.addHeader("Access-Control-Allow-Headers", "useXDomain, withCredentials, Overwrite, Destination, Content-Type, Depth, User-Agent, Translate, Range, Content-Range, Timeout, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Location, Lock-Token, If");
        response.addHeader("Access-Control-Expose-Headers", "DAV, content-length, Allow");
        response.addHeader("Access-Control-Max-Age", "86400");

    }
}

Am I missing anything?

7
  • Are you authenticating against one server and then trying to make unauthenticated requests to the other? If that is the case, then it is not a surprise you are getting 401. Nothing to do with CORS. Commented Dec 30, 2014 at 11:21
  • I am authenticating on both the servers. and its working properly. My problem is, once the authentication is done, when i request a resource from master, i am getting 401. Commented Dec 30, 2014 at 11:23
  • Do I need to send my credentials with requests made after initial authentication? If yes, how do I send it? Commented Dec 30, 2014 at 11:38
  • 2
    I see your mistake... withCredentials is not a header, but XHR option - docs.angularjs.org/api/ng/service/$http. Without this option cross-origin requests don't contain cookies. Commented Dec 30, 2014 at 11:48
  • No... withCredentials will enable cookies in general. So your requests will be able to include JSESSIONID - thus allowing HTTP session where Spring Security stores information about the authentication. Just add config.withCredentials = true instead of setting it as header. Commented Dec 30, 2014 at 12:40

1 Answer 1

2

You are incorrectly setting withCredentials as a request header. This is XHR option and should be present directly on the config:

config.withCredentials = true;

This option will enable cookies for your requests. Your requests will be able to include JSESSIONID, thus allowing HTTP session where Spring Security stores information about the authentication.

And as discussed in the chat (see question comments) - be aware that if the two servers are running on the same domain, they will share cookies. That might cause issues (sending incorrect JSESSIONID) so you need to access those servers under different host name.

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

Comments

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.