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?

sadhvaryu
  • 300
  • 1
  • 2
  • 9
  • 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. – Pavel Horal Dec 30 '14 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. – sadhvaryu Dec 30 '14 at 11:23
  • Do I need to send my credentials with requests made after initial authentication? If yes, how do I send it? – sadhvaryu Dec 30 '14 at 11:38
  • 2
    I see your mistake... `withCredentials` is not a header, but XHR option - https://docs.angularjs.org/api/ng/service/$http. Without this option cross-origin requests don't contain cookies. – Pavel Horal Dec 30 '14 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. – Pavel Horal Dec 30 '14 at 12:40
  • Thanks for helping me out. I have made changes as suggested by you. But I am still getting that error. If I am not wrong, it is sending incorrect jsessionid. Is it because both of my servers are running on localhost i.e same domain? do I need to make any other changes? – sadhvaryu Dec 30 '14 at 13:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/67914/discussion-between-pavel-horal-and-sadhvaryu). – Pavel Horal Dec 30 '14 at 13:00

1 Answers1

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.

Community
  • 1
  • 1
Pavel Horal
  • 17,782
  • 3
  • 65
  • 89