Grooming Cookies to Support Session Sharing across Sub-Domains

I recently had to figure out a solution to a problem that others may face, so I thought I’d share. The solution turned out to be pretty trivial once it was understood, but it took a little digging to get there.

I wanted to use separate sub-domains for the same web application, in which each sub-domain would point to the same app but would cause slightly different behavior within the app. Specifically, the sub-domains correspond to geographical region names and they cause the app to load content that is geo-coded within the specified region.

This part was easy enough to set up. You can add a wildcard A record into DNS so that all sub-domains map to the same IP, and then build logic into your app that parses the sub-domain and handles things accordingly. The problem was that the user’s session would be lost if the user clicked from one sub-domain to another within the same app. This clearly would not work, as the user’s login state would be lost, etc.

This was happening because of the rules related to which cookies in a browser are allowed to be passed into the header of a request: only those cookies which were set by the same domain, or sub-domain, of the server domain are passed over the http request. After some digging, I realized that the real root issue here was that tomcat was automatically setting the JSESSIONID cookie into the HTTP response header in such a way that it was only associated with the specific sub-domain of the request/response at hand. So, for example, if newyork.sportsvite.com was requested, the browser would only send back the JSESSIONID cookie that was explicitly set by requests to that same sub-domain. What had to be done was to somehow override this behavior and set the Domain property on this cookie to the value of the base domain, sportsvite.com. With this logic in place, the browser would send this cookie back on all requests to any sub-domain under that base domain.

In order to do this, you need to groom the cookies on each incoming request so that this Domain property is set accordingly. Once this is done, all requests coming in for different sub-domains will associate that same cookie to the request and therefore use the JSESSIONID value to match up the same single session within servlet container.

So, it’s really easy in the end. Basically, this cookie grooming logic needs to be placed somewhere along the request processing flow - this could be a Servlet Filter, a Tomcat Valve, or even down in the app framework you’re using. In my case, I chose to keep it down in the app framework, and thus added logic into a custom subclass of the Struts RequestProcessor class. Here is the generic method that you could adapt to your needs:

void performCookieGrooming(HttpServletRequest request, HttpServletResponse response) {

Cookie[] cookies = request.getCookies();
HttpSession session = request.getSession();

String cookieDomain = “sportsvite.com”;
String cookieNameSessionId = “JSESSIONID”;

if (session.isNew()) {
/**
* Create and add a NEW JSESSIONID cookie with the domain set accordingly
*/
Cookie newCookie = new Cookie(cookieNameSessionId, session.getId());
newCookie.setDomain(cookieDomain);
newCookie.setMaxAge(-1);
newCookie.setPath(”/”);
if (request.isSecure()) {
newCookie.setSecure(true);
}
response.addCookie(newCookie);
} else {
/**
* Loop through all cookies in the request, and find the one(s) corresponding to JSESSIONID
*/
if (cookies != null && cookies.length > 0) {
Cookie cookie;
for (int i = 0; i < cookies.length; i++) {
cookie = (Cookie) cookies[i];
/**
* Do the manipulation for session Id cookie(s) only
*/
if (cookieNameSessionId.equals(cookie.getName())) {
String value = cookie.getValue();
cookie.setDomain(cookieDomain);
/**
* Also, to be sure, set the sessionID into the value
* …not sure if this is really needed.
*/
cookie.setValue(session.getId());
}
}
}
}
}

Notice that this method loops through cookies and grooms those that are JSESSIONID cookies. It works fine, and now I’m rolling with multiple sub-domain on the same app. Hope this helps someone!

Leave a Reply

You must be logged in to post a comment.