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.
April 26, 2015 at 3:32 AM
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.
June 30, 2015 at 6:16 AM
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
June 30, 2015 at 7:47 AM
If you send me your code via email or GitHub I will take a look and help you fix it. alanjames1987@gmail.com
July 1, 2015 at 5:45 AM
I believe this is because
req.param
has been decremented in the newest version of Express. Everywhere I usereq.param
you will have to usereq.query
orreq.body
.I will update the tutorial to reflect that.
July 7, 2015 at 12:18 PM
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.
July 11, 2015 at 6:23 PM
I haven’t used the newest Cordova. I will have to test it out. Thanks.