Nodejitsu

Save time managing and deploying your node.js app. Code faster with jitsu and npm

sessions and cookies in node

About the author

Name
Location
Worldwide
nodejitsu nodejitsu

Session management is a major piece of any serious web application. When building a site, it is likely you will want the ability to persist a user's identity over multiple requests without having to have them re-login again and again. A common method for persisting a user's login over multiple http requests, is called setting a "cookie". Now almost all web developers have some idea of what a cookie is, but in this article we will dive into the specifics of actually implementing a cookie / session persistence system from scratch in node.js through exploring the session.js library and the response library.


Getting Started

First, we are going to need some logic for implementing session management. Crack JavaScript developer inimino was nice enough to release the following module, so we will build on that. In this module, only one method is exported: "lookupOrCreate". If we dive into this method a little bit, we can see it takes two options, a request object and an options hash.

This "lookupOrCreate" method will inspect the headers of the incoming request object and determine if there is any value set for the cookie field ( note: the actual header name is "Set-Cookie", but node refers to this header as "cookie"). If lookupOrCreate finds a cookie, it will retrieve the session object from memory, else it will create a new session for that request.

Now, the tricky part here is that if we've created a new session, we need to set the cookie in the response header so the client knows it has a session. Unless we explicitly set a cookie in the response header, "lookupOrCreate" will never find your session cookie.

To set the cookie in the http response you can do something like:

 var session = sessions.lookupOrCreate(request,{
   lifetime:604800
 });

 response.writeHead(200, {
   'Content-Type': 'text/plain', 
   'Set-Cookie', session.getSetCookieHeaderValue()
 });

Even better then using response.write though, is using response.setHeader. This will not close the response, and allow for further manipulation down the request/response processing chain...kinda like a proper middle-ware!

 response.setHeader('Set-Cookie', session.getSetCookieHeaderValue());

Note: You will need the response module for this to work, it should be pulled into core eventually.


Creating a super simple session middle-ware

In node.js, an accepted standard for building middleware is the following:

 function( request, response, callback) {

   // perform some logic on the request or response objects
   console.log(request.url);


   // then fire our callback, and pass the request 
   // and response objects down the chain
   callback(request, response, function(){

   });

 }

Following this standard, a "middle-ware" for node.js's httpServer is nothing but a function that accepts three arguments: a request object, a response object, and a callback. Building on this very simple convention, we can implement de-coupled layers of middleware, each with its own responsibility. In our case, our middleware will be responsible for establishing sessions!


get session.js!


Using session.js as a middle-ware

var http = require('http'),  
    session = require('./lib/core').session;

// let's create a basic http server!
http.createServer(function (request, response) {

  // before we process any part of the request, let's use the session middle-ware!
  session(request, response, function(request, response){

    // now we can access request.session

    // after the session middleware has executed, let's finish processing the request
    response.writeHead(200, {'Content-Type': 'text/plain'});
    response.write('request.session: \n' + JSON.stringify(request.session, 2, true));
    response.end();

  });

}).listen(8080);

/* server started */  
console.log('> hello world running on port 8080');  


Magic Monkey Punched Middle-ware Sessions (automatically patches httpServer)

var http = require('http'),  
    session = require('./lib/core').magicSession(); // special magic, now all requests have sessions!

// let's create a basic http server!
http.createServer(function (request, response) {

  // now we can access request.session

  // let's finish processing the request
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.write('request.session: \n' + JSON.stringify(request.session, 2, true));
  response.end();

}).listen(8080);

/* server started */  
console.log('> hello world running on port 8080');  


Creating a super simple login / logout feature

One of the best things about having a persistent session object per user, is having the ability to create user logins. The actual way you want to implement your login is somewhat arbitrary. Here is a basic pattern to follow. Please, remember this method is just an example:

    var http = require('http'),
        session = require('./lib/core').magicSession();

    // let's create a basic http server!
    http.createServer(function (request, response) {

      // please note: this is just an example of how to hook auth into session.js, its not ideal at all

      // super basic logout
      if(request.url === '/logout'){
        request.session.data.user = "Guest";
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.write('You\'ve been logged out');
        response.end();
        return;
      }

      // let's hardcode a username and password variable into the url
      var urlParams = require('url').parse(request.url, true).query || {};

      if(typeof urlParams.name != 'undefined'){
        // if the "name" parameter has been sent, lets log in as that user
        request.session.data.user = urlParams.name;
      }

      // request.session.data.user always defaults to "Guest"
      if(request.session.data.user == "Guest"){
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.write('Hello, you are the Guest user');
        response.end();
      }
      else{
        response.writeHead(200, {'Content-Type': 'text/plain'});
        response.write('Hello, you are ' + request.session.data.user);
        response.end();
      }


    }).listen(8080);

    /* server started */  
    console.log('> hello world running on port 8080');

Once you have this running you can do the following:

GET http://localhost:8080/
// returns: Hello, you are the Guest user

GET http://localhost:8080/?name=Marak
// returns: Hello, you are Marak

GET http://localhost:8080/
// returns: Hello, you are Marak

GET http://localhost:8080/logout
// returns: You've been logged out

GET http://localhost:8080 
// returns: Hello, you are the Guest user

Huzaah! There you go! session.js is open-source, so lets get hacking!