0

I have been experimenting with Ember.js and Node.js, and have run into a problem. I have protected my API routes on the server with the standard Express.session system, but I have run into a problem when those APIs are serving an Ember.js application. Since the Ember app does not have the ability to store values in req.session, my app doesn't function. How should I do my authentication so that I still can session-protect my API? Here is some of my current server login code:

a "check login" function:

var checkLogin = function(req, res, callback) {
    if (req.session.user) {
      callback();
    } else {
      res.send({error: "AuthRequired"});
    }
  };

Error when Ember makes a request:

TypeError: Cannot read property 'user' of undefined

Middleware setup:

app.configure(function () {
  app.use(express.bodyParser());
  app.use(express.static(__dirname + '/static/'));
  app.use(express.cookieParser(<SECRET>));
  app.use(express.session());
  //to not care about invalid JSON requests
  app.use(function(err, req, res, next) {
    if (err.message == 'invalid json')  {
        next()
    } else {
        next(err)
    }
  });
});
Brad Ross
  • 451
  • 8
  • 26
  • Could you post your Express app configuration (middleware and such)? – robertklep Apr 02 '13 at 06:34
  • updated with the middleware info. – Brad Ross Apr 02 '13 at 17:30
  • Could it be you're declaring your middleware *after* your routes? Otherwise, I don't see why `req.session` can be undefined (when a client doesn't send a session cookie, that still would create `req.session`, just an empty one). – robertklep Apr 02 '13 at 18:58
  • Nope. My routes are after the middleware setup. Strange huh? See the below thread; I thought it was because the app wasn't setting a session for the AJAX client. – Brad Ross Apr 03 '13 at 00:48
  • Yes, very strange indeed. I remember one case where the same happened, but that was related to a piece of middleware (`i18next`) that internally pushed `app.router` onto the middleware stack, *before* the other session-related middleware were loaded, but that doesn't seem to be the case with your code. – robertklep Apr 03 '13 at 06:04

1 Answers1

3

Have you tried Passport?
This middle-ware adds user to your session, I recommend trying its passport-local provider.
The guide on the website may not be fully working code, you better refer to the example folder on git repo.

UPDATE: It may be the sequence of config that is not okay. Here's my config for Locomotive server (replace this with app), try it out.

this.use(poweredBy(null));
this.use(express.favicon());
this.use(express.logger('dev'));
this.use(express.compress());
this.use(express.cookieParser());
this.use(express.static(__dirname + '/../../public'), { maxAge: 60*10*1000 });
this.use(express.bodyParser());
this.use(express.methodOverride());
this.use(express.session({ secret: '<SECRET>' }));
// Initialize Passport!  Also use passport.session() middleware, to support
// persistent login sessions (recommended).
this.use(flash());
this.use(passport.initialize());
this.use(passport.session());
this.use(this.router);
leesei
  • 6,020
  • 2
  • 29
  • 51
  • The problem with that is it is just what I had before: The AJAX request from the client still doesn't have the cookie/session on it. I'm probably going to implement my own simple token system for the requests. – Brad Ross Apr 02 '13 at 17:18
  • I suspect it may be a setup issue, have you tried to run the `passport-local` example code? – leesei Apr 02 '13 at 17:21
  • What I mean is that the session for passport is stored in the request (I think). What that means is that when a client makes a request, it checks that a session variable is stored in that request. When I login to my service, it sets a cookie (I think) on the browser. When I make a request from my Ember client however, the AJAX is not coming from my browser, and does not have access to my cookie. Correct me if I am wrong, but this is probably why my system currently doesn't work. – Brad Ross Apr 02 '13 at 17:28
  • 1
    AFAIK, a session ID is created when a User Agent (read: browser) connects to the server. This ID is stored as cookie cookie on client side and then used to look up the info in MemoryStore. `req.session.user` is the object stored in the MemoryStore.
    AJAX is also HTTP so the cookie should have been sent, could you check if the `sid` cookie is on the request header with WebInspector/Firebug?
    See [How do sessions work in Express with NodeJs?](http://stackoverflow.com/questions/5522020/how-do-sessions-work-in-express-with-nodejs)
    – leesei Apr 02 '13 at 17:41
  • Not to sound like a noob, but how do I check this? – Brad Ross Apr 02 '13 at 17:45
  • For Chrome, open the page, F12. Go to the [Network Panel](https://developers.google.com/chrome-developer-tools/docs/network) (probably need to reload for it to pick up the traffic), click on your XHR (may need to enable logging of XHR, I'm not sure if the default is on or not). Nvrmind, every one starts with a blank slate. – leesei Apr 02 '13 at 17:52
  • Yup: it's there: `Cookie:connect.sid=s%3AD0KTNAoYBoOxSBzij0l2wySb.76ASkxrvCJFcMWROuiyQirKcEQAbaMjjuGauqqAZEgU` – Brad Ross Apr 03 '13 at 01:27
  • Then the cookie should be working fine, have you tried to dump `cookie` with `console.log(req.cookies['connect.sid']);`? Do refer to [See How do sessions work in Express with NodeJs?](http://stackoverflow.com/questions/5522020/how-do-sessions-work-in-express-with-nodejs) and make sure you understand the documents. Again, `user` is a custom field and you have to put in yourself. – leesei Apr 03 '13 at 04:48
  • I understand. I just don't get why it said `session` was undefined even though the cookie exists and I clearly created a new session... Also, I console logged what you said to do (`req.cookies['connect.sid']`) and got a similar error: `Cannot read property 'connect.sid' of undefined`. So strange... – Brad Ross Apr 03 '13 at 04:59
  • I just implemented Passport Local for the first time, and now I get 404s: `CANNOT GET '/tasks` – Brad Ross Apr 05 '13 at 02:21