Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confusing documentation in passportjs.org/guide #29

Closed
therealplato opened this issue May 22, 2012 · 2 comments
Closed

Confusing documentation in passportjs.org/guide #29

therealplato opened this issue May 22, 2012 · 2 comments

Comments

@therealplato
Copy link

Hey, I'm new to Node and Express and Passport, so I am muddling my way through and trying to get a site set up with authentication and sessions.

I'm looking at the authenticate page. The first example reads:

"authenticate()'s function signature is standard Connect middleware, which makes it convenient to use as route middleware."

app.post('/login', 
  passport.authenticate('local'),
  function(req, res) {
    // If this function gets called, authentication was successful.
    // `req.user` property contains the authenticated user.
  });

And the last example on that page reads:

app.get('/login', function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err) { return next(err) }
    if (!user) { return res.redirect('/login') }
    req.logIn(user, function(err) {
      if (err) { return next(err); }
      return res.redirect('/users/' + user.username);
    });
  })(req, res, next);
});

"In this example, note that authenticate() is called from within the route handler, rather than being used as route middleware. This gives the callback access to the req and res objects through closure."


I thought middleware was applied in a chain, passing the req/res objects down to whatever finally sends a response. But the first example looks to me like that is also calling authenticate() from within a route handler. Your configuration page has example code:

app.configure(function() {
  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);
  app.use(express.static(__dirname + '/../../public'));
});

This looks like the Express middleware chain to me, but you are not calling authenticate() anywhere.

So. Is there a way for me to authenticate each and every request somewhere in my chain of middleware, before it's passed to app.router? I want to check if the request came from an authenticated user in my routing functions, without calling authenticate() on a per-route basis.

@ForbesLindesay
Copy link
Contributor

Yes, you can simply write your own route middleware like so:

function checkAuth(req,res,next){
    if(req.user) next();//Forward the request so it can be handled by your router
    else res.send(403);//send access denied
}

app.configure(function() {
  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);
  app.use(express.static(__dirname + '/../../public'));
});

app.get('/login',function(req,res){
    //Serve your login page here
});
app.post('/login', 
  passport.authenticate('local'),
  function(req, res) {
    // If this function gets called, authentication was successful.
    // `req.user` property contains the authenticated user.
});

app.all('*', checkAuth);

//Serve any other pages here:

app.get('/secure', function(req,res){
  res.json(req.user);
});

The way this works is that Express applies routes in order, when they match. We have our login methods before we check for authentication, so users can access it to sign on, then we check auth using app.all('*', checkAuth) which works because all matches all request methods (GET, PUT, POST etc.) and '*' matches all paths ('example.com/', 'example.com/secure', 'example.com/other' etc.)

If you need to be able to define more complex authorization rules based on roles you can try my https://github.com/ForbesLindesay/connect-roles (if you have any problems, create an issue). It comes with a built in require('connect-roles').isAuthenticated middleware.

@therealplato
Copy link
Author

@ForbesLindesay Awesome this answers my questions; thank you for the explanation. -plato

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants