3

I've extended the apostrophe-express module implementing logic to check cookies in the request headers. One of the cases in this check is to auto login users. If a cookie key/val matches a preset flag value, then I would like to do a lookup for the user in the aposUsersSafe collection (based on an email address) and, if the user exists in the collection, automatically sign him into the cms.

Currently, I have implemented the user lookup by running a mongo query for the user based on email:

var collection = db.collection('aposUsersSafe');

    collection.find({email: email}).toArray(function (err, result) {
      if (err) {
        deferred.reject(new Error(error));
      } else if (result.length) {
        deferred.resolve(result);
      } else {
        console.log('User not found');
      }

But I see that the apostrophe-login module provides methods for authentication and permissions via passport. Would extending apostrophe-login and passport be the way to implement this auto login solution? Thanks!

lance-p
  • 1,050
  • 1
  • 14
  • 28

1 Answers1

4

As I mentioned in answering your earlier question I'm the principal architect of Apostrophe at P'unk Avenue.

There is actually a complete implementation of autologin in our demo project, ripe for the borrowing (: We wanted to automatically log the user in so that folks wouldn't give up before even seeing the user interface.

It's quite short, so here it is:

module.exports = {
  construct: function(self, options) {
    self.pageBeforeSend = function(req, callback) {
      if (!req.cookies.demo_autologin) {
        return self.apos.users.find(req, { username: 'admin' }).permission(false).toObject(function(err, user) {
          if (err) {
            return callback(err);
          }
          if (!user) {
            return callback(null);
          }
          req.login(user, function(err) {
            if (err) {
              return callback(err);
            }
            // Start a whole new request, but logged in. After this they
            // have the cookie so they can log out and back in normally if they want
            req.res.cookie('demo_autologin', 1);
            return req.res.redirect('/');
          });
        });
      }
      return callback(null);
    };
  }
};

Of course you need to enable the demo-autologin module in app.js by including it in the modules property with the rest.

Here's how this module works:

  1. It provides a pageBeforeSend method, which gets called just before a page is sent to the browser.

  2. It checks whether the demo_autologin cookie has been set yet.

  3. If not, it finds the admin user via a cursor provided by the find method of the apostrophe-users module, using permission(false) to bypass the permissions checks that would normally limit what can be found.

  4. It invokes req.login, a method provided by passport that makes it very easy indeed to log a user in programmatically.

  5. It sets the cookie via req.res.cookie. The res object can always be accessed from req and vice versa. In Apostrophe only req is typically passed around, because req.res is available and because in most cases you'll be adding more data to req, not responding directly.

  6. It redirects to the home page, so that the whole page loads as a logged-in experience.

Naturally you would decide which user to look for according to different criteria than "just make everybody admin," but it sounds like you have a handle on that part and this code should easily adapt to your needs.

(It occurs to me that this code might encounter a redirect loop if the user refused to accept even a plain old session cookie. Regular login wouldn't work then anyway, but if you wanted to, you could track the situation via the query string and tell the user to enable cookies if they get here twice.)

This answer has been corrected to include the req argument to find.

Community
  • 1
  • 1
Tom Boutell
  • 7,281
  • 1
  • 26
  • 23