NodeJS + Express: How to secure a URL

Fabio B. picture Fabio B. · Sep 5, 2012 · Viewed 25.5k times · Source

I am using latest versions of NodeJS and ExpressJS (for MVC).

I usually configure my rest paths like this, for example:

app.get('/archive', routes.archive);  

Now i want my /admin/* set of URLs to be secured, I mean I need just simple authentication, it's just a draft.

When a user tries to access, for example, /admin/posts, before sending him the corresponding view and data, I check for a req.session.authenticated. If it's not defined, I redirect to the login page.

Login page has a simple validation form, and a sign-in controller method: if user does send "right user" and "right password" I set the session variable and he's authenticated.

What I find difficult, or I don't understand, is how to actually make the "filter" code, I mean, the auth check, before every /admin/* path call.

Does this have something to do with "middleware" express functions?

Thank you

Answer

Michelle Tilley picture Michelle Tilley · Sep 5, 2012

Yep, middleware is exactly what you want. A middleware function is just a function that works just like any other Express route handler, expept it gets run before your actual route handler. You could, for example, do something like this:

function requireLogin(req, res, next) {
  if (req.session.loggedIn) {
    next(); // allow the next route to run
  } else {
    // require the user to log in
    res.redirect("/login"); // or render a form, etc.
  }
}

// Automatically apply the `requireLogin` middleware to all
// routes starting with `/admin`
app.all("/admin/*", requireLogin, function(req, res, next) {
  next(); // if the middleware allowed us to get here,
          // just move on to the next route handler
});

app.get("/admin/posts", function(req, res) {
  // if we got here, the `app.all` call above has already
  // ensured that the user is logged in
});

You could specify requireLogin as a middleware to each of the routes you want to be protected, instead of using the app.all call with /admin/*, but doing it the way I show here ensures that you can't accidentally forget to add it to any page that starts with /admin.