title: Node.js Express + Passport + Cookie Sessions n > 1 servers
body: <p>From the Passport docs:</p>
  
  <blockquote>
    <p>In a typical web application, the credentials used to authenticate a
    user will only be transmitted during the login request. If
    authentication succeeds, a session will be established and maintained
    via a cookie set in the user's browser.</p>
    
    <p>Each subsequent request will not contain credentials, but rather the
    unique cookie that identifies the session. In order to support login
    sessions, Passport will serialize and deserialize user instances to
    and from the session.</p>
  </blockquote>
  
  <p>So, being that the authentication is maintained in the client's browser, I should be able to scale the web servers to > 1 (each server uses same database) and have Passport deserialize user from an ID stored in a cookie regardless if the server has seen the user before. If the server <em>has</em> seen the user before but no cookie exists, I would expect Passport to fail the authentication...but I can't even get that far with n > 1 servers. </p>
  
  <p><em>With 1 server process, Passport works fine:</em></p>
  
  <p>The server is more or less verbatim of docs on both servers (after much trials w/ connect references and such):</p>
  
  <pre><code>app.configure(function() {
    app.use(express.static('public'));
    app.use(express.cookieParser());
    app.use(express.bodyParser());
    app.use(express.session({ secret: 'keyboard cat' }));
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(app.router);
  });
  </code></pre>
  
  <p>When a user login is successful, right before I return the HTTP request, I log <code>req.user</code> and <code>req.session</code>:</p>
  
  <pre><code>console.log(req.user);
  console.log(req.session);
  res.send(200, req.user);
  // {"cookie":{
  //   "originalMaxAge":null,
  //   "expires":null,
  //   "httpOnly":true,
  //   "path":"/"
  //  },
  //  "passport":{"user":"ID"}}
  </code></pre>
  
  <p>When the HTTP request returns, the web app requests <code>/</code> and expects the server(s) to set <code>req.user</code> with ID <code>ID</code> from the cookie passed:</p>
  
  <pre><code>passport.deserializeUser(function(req, user_id, cb) {
    console.info('Passport deserializing user: '
      .concat(user_id));
    console.log(req.user);
    console.log(req.session);
    // ...
    // cb(null, user);
  });
  </code></pre>
  
  <p>With 1 server running, this logs as:</p>
  
  <pre><code>Passport deserializing user: ID
  undefined
  undefined
  </code></pre>
  
  <p>Immediately after the callback <code>cb(null, user)</code> and before I return the request, I log <code>req.user</code> and <code>req.session</code> and see what I would expect!</p>
  
  <p><strong>Now, with n > 1 servers running</strong>, let's say 2, if the web app requests <code>/</code> from server 2 and expects it to set <code>req.user</code> with ID <code>ID</code> from the cookie passed (originally set by logging into server 1), I don't even see the deserialize function called! When I added logging to the beginning of the HTTP route (after middleware):</p>
  
  <pre><code>console.log(req.user);
  console.log(req.session);
  </code></pre>
  
  <p>I see:</p>
  
  <pre><code>undefined
  // {"cookie":{
  //   "originalMaxAge":null,
  //   "expires":null,
  //   "httpOnly":true,
  //   "path":"/"
  //  },
  //  "passport":{}}
  </code></pre>
  
  <p>...which tells me something is up with the cookie, but what? Both server processes are on Heroku behind the same DNS. I have read various discrepancies about needing some "shared session" store for this...but that's what a cookie is at the client's browser level. Please help! Express is the latest 3.X and Passport is 2.1.</p>