Cordova and Session Cookies

As of Cordova 5.2.0 on Android 5.1 cookies are working.
I will be investigating other platforms, like iOS, soon.

I’ve talked many times about my love of Cordova. I like how I can use my existing knowledge and code to build a mobile application with additional abilities than a web application. While I know how to a write native Android application, I still prefer to do my initial prototyping and launch in Cordova.

I honestly like everything about Cordova aside from the fact that you can’t use cookie based sessions.

In this post I will show you how to do so in Express 4 using jQuery AJAX calls and some simple code.

Cookies vs Local Storage

Cookies have been available for over twenty years for storing information on the client (browser), but local storage has been introduced pretty recently, with HTML5.

The main difference between cookies and local storage is that cookies are sent to the server with every request, while local storage variables aren’t. This means a server can create a cookie on your browser when you log into, lets say Facebook, that stores information about your session. The cookie is sent back on each new request to the Facebook servers, where it is compared against a database of session data and eventually matched with session data specific to you.

Unlike a normal browser, Cordova cannot hold cookies. It won’t accept them if a server sends them and so a workaround has to be created.

The Plan

jQuery

Let’s be honest, you’re probably using jQuery for your AJAX calls. If you aren’t then you probably should be because jQuery has a great method called ajaxPrefilter, which can be used to run a function before all AJAX calls. It accepts a function with three parameters, options, originalOptions, and jqXHR.

In this function you can alter the XHR options data being sent to the server on every AJAX call, which means you can add additional parameters, like a session id parameter, in place of a cookie, which would store a session id.

Express Middelware

Just like jQuery, Express has a function that can be run before all route callback functions. This function is called use and is the way you have to load in Express session.

The use function accepts a function with three parameters, a request object (req), a response object (res), and a next function.

In the function you can alter anything about the request or response objects, and once you call next Express actives and runs the next middleware in the middleware chain until it reaches the route handler.

This means we can intercept the additional parameter we send from jQuery, the session id, and turn it into a cookie header on the request object before Express session tries to use it to find a user’s session.

The greatest thing about this is that it changes none of your other code. You jQuery AJAX calls remain the same and so do your Express route handlers.

The only thing that changes is the code that runs before them.

Let’s Finally Get to Coding

Front End

Below is code that should go somewhere in your front end code. The location is entirely dependent on your architecture, but make sure it loads before you make any AJAX calls.

For the code below I am using the node-uuid library to generate a uuid as a session id, but you can generate your session ids however you want, just make sure they are unique.

Additionally mySessionKey can be anything you want.

var sessionId = localStorage.getItem('myCookieName');

// if there was no localStorage for the session id 
// the application is being run for the first time
// the session id must be created
if (!sessionId) {
	sessionId = uuid.v4();
	localStorage.setItem('myCookieName', sessionId);
}

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {

	// if there is data being sent
	// add the sessionId to it
	if (options.data) {
		options.data += '&sessionId=' + sessionId;
	}

	// if there is no data being sent
	// create the data and add the sessionId
	else {
		options.data = 'sessionId=' + sessionId;
	}

});

That is all for the front end.

Back End

The back end is slightly harder to write, but not by much.

It will require that you use two NPM modules. One is called cookie and the other is called cookie-signature.

Include these in your application where ever you add the code below.

Just like the front end the location of this code is dependent on your architecture, however, the code below should be added before the Express session middleware.

In this code I assume your Express server is called app and that your session cookie is called connect.sid, which is the default name. If these are not correct change them.

You will also need to know your session secret key. The Express session example code on GitHub uses keyboard cat, so that is what I have used below.

app.use(function(req, res, next) {

	var sessionId = req.param('sessionId');

	// if there was a session id passed add it to the cookies
	if (sessionId) {

		var header = req.headers.cookie;

		// sign the cookie so Express Session unsigns it correctly
		var signedCookie = 's:' + cookieSignature.sign(sessionId, 'keyboard cat');

		req.headers.cookie = cookie.serialize('connect.sid', signedCookie);

	}

	next();

});

You must put the that code above the Express session middleware configuration, which we will configure with the following. In this example I assume you have required the `express-session` into a variable called `expressSession`.

app.use(function(req, res, next) {

	expressSession({
		'cookie': {
			'httpOnly': false,
			'maxAge': 1000 * 60 * 60 * 24 * 60,
		},
		'name': 'connect.sid',
		'secret': 'keyboard cat',
		'saveUninitialized': true,
		'genid': function() {

			var sessionId = req.param('sessionId');

			if (sessionId) {
				return req.param('sessionId');
			}

			return uuid;

		}

	})(req, res, next);

});

We use the `genid` method to generate the session id using the session id passed from the ajax call.

We have to call the `expressSession` function, passing the `req`, `res`, and `next` so that the `genid` method has access to `req` and thus the `sessionId` parameter.

That’s All

Your front end code will generate a random session id, store it in localStorage, and add it to all AJAX requests via the ajaxPrefilter method build into jQuery.

Your back end code will accept this request from AJAX, look for the sessionId parameter and add it’s value into the request cookie headers. Once the Express session middleware is called the session id will exist as part of the cookie header in the request object, which Express session will use to access the session relevant to the user.

Easy to write, use, and explain.

I love when code is simple.

6 Comments

  1. Outstanding. I have been fighting with cordova and session cookies for over a week now. I use express on the backend, and your solution works seamlessly. Thank-you so much for taking the time to write this post.

  2. Hi, interesting workaround.. but it’s not working in my case…I pass the sessionid to the express server, but the session seems to change every time i call it from my cordova app. What could i be missing ? Thanks in advance

  3. FYI – not sure if Cordova fixed anything, but cookies are working fine for our app when deployed to iOS 8 devices. In memory cookies as well as persistent cookies that survive across app restarts.

Leave a Reply