Passport-http-bearer: How do scopes work?

Created on 5 Mar 2012  路  3Comments  路  Source: jaredhanson/passport-http-bearer

Hi Jared,

I have a hard time wrapping my head around how passport deals with scopes. Here is my scenario:

I have a token store, each token has a scope attached to it. I have some routes that only tokens with admin scope can access and others that require normal token access. In my app I would do something like this:

app.use('/v1', passport.authenticate('bearer', { session: false }):

to catch the normal case and for specific routes that require admin rights I would add something like this into the route's middleware, like
.. passport.authenticate('bearer', { session: false, scopes: ['admin']})

Is this supported by passport or do I have to do it differently?

Most helpful comment

@mwawrusch I've got a solution to this that I'm happy with and is working well, which is a slightly cleaned-up version of what you mention.

You can now pass a third argument to success, and that is attached by Passport at req.authInfo

passport.use(new BearerStrategy(
  function(token, done) {
    User.findOne({ token: token }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      return done(null, user, { scope: 'profile' });
    });
  }
));

The info argument can then be used in middleware further down the chain to implement authorization and access control.

app.get('/api/userinfo', 
  passport.authenticate('bearer', { session: false }),
  function(req, res, next) {
    // access control middleware to check for required scope
    if (req.authInfo.scope != 'profile') {
      res.statusCode = 403;
      return res.end('Forbidden');
    }
    return next();
  }
  function(req, res) {
    res.json(req.user);
  });

The info is just a generic JSON object, so the app will need to settle on conventions for what is supplied. I'm hoping that this will prove useful for implementing general purpose authorization middleware as well.

The feature coincides with the development of OAuthorize and OAuth2orize, which make use of it. They can be used to implement OAuth 1.0 and 2.0 servers respectively. I think I've seen a Quora page on this subject that you've made. It'd be great to get these added to that!

As always, send me any feedback. Cheers!

All 3 comments

Just for completeness, here is what I am doing now: I simply add the scopes to the user object and use req.user... and at a later stage I check if the specific route and scope match.

@mwawrusch I've got a solution to this that I'm happy with and is working well, which is a slightly cleaned-up version of what you mention.

You can now pass a third argument to success, and that is attached by Passport at req.authInfo

passport.use(new BearerStrategy(
  function(token, done) {
    User.findOne({ token: token }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      return done(null, user, { scope: 'profile' });
    });
  }
));

The info argument can then be used in middleware further down the chain to implement authorization and access control.

app.get('/api/userinfo', 
  passport.authenticate('bearer', { session: false }),
  function(req, res, next) {
    // access control middleware to check for required scope
    if (req.authInfo.scope != 'profile') {
      res.statusCode = 403;
      return res.end('Forbidden');
    }
    return next();
  }
  function(req, res) {
    res.json(req.user);
  });

The info is just a generic JSON object, so the app will need to settle on conventions for what is supplied. I'm hoping that this will prove useful for implementing general purpose authorization middleware as well.

The feature coincides with the development of OAuthorize and OAuth2orize, which make use of it. They can be used to implement OAuth 1.0 and 2.0 servers respectively. I think I've seen a Quora page on this subject that you've made. It'd be great to get these added to that!

As always, send me any feedback. Cheers!

Very nice, thank you.

On Fri, Jul 13, 2012 at 8:36 AM, Jared Hanson <
[email protected]

wrote:

@mwawrusch I've got a solution to this that I'm happy with and is working
well, which is a slightly cleaned-up version of what you mention.

You can now pass a third argument to success, and that is attached by
Passport at req.authInfo

passport.use(new BearerStrategy(
  function(token, done) {
    User.findOne({ token: token }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      return done(null, user, { scope: 'profile' });
    });
  }
));

The info argument can then be used in middleware further down the chain to
implement authorization and access control.

app.get('/api/userinfo',
  passport.authenticate('bearer', { session: false }),
  function(req, res, next) {
    // access control middleware to check for required scope
    if (req.authInfo.scope != 'profile') {
      res.statusCode = 403;
      return res.end('Forbidden');
    }
    return next();
  }
  function(req, res) {
    res.json(req.user);
  });

The info is just a generic JSON object, so the app will need to settle
on conventions for what is supplied. I'm hoping that this will prove
useful for implementing general purpose authorization middleware as well.

The feature coincides with the development of OAuthorize and OAuth2orize, which make use of it. They
can be used to implement OAuth 1.0 and 2.0 servers respectively. I think
I've seen a Quora page on this subject that you've made. It'd be great to
get these added to that!

As always, send me any feedback. Cheers!


Reply to this email directly or view it on GitHub:

https://github.com/jaredhanson/passport-http-bearer/issues/2#issuecomment-6966368

Was this page helpful?
0 / 5 - 0 ratings

Related issues

carera picture carera  路  4Comments

wcbeard picture wcbeard  路  12Comments

alivedise picture alivedise  路  21Comments

funston picture funston  路  7Comments

thimbl picture thimbl  路  6Comments