jaredhanson / passport-http

HTTP Basic and Digest authentication strategies for Passport and Node.js.

Home Page:https://www.passportjs.org/packages/passport-http/?utm_source=github&utm_medium=referral&utm_campaign=passport-http&utm_content=about

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Example for mixing Basic & Local strategies

nestradaOBS opened this issue · comments

Hello,

This is not really an issue but is there a way to mix both Basic HTTP and Local passport strategies? The reason is that I would like to use Basic for easy testing with supertest (using request(app).auth()), and some clients which are totally restful otherwise a simple login form using the Local POST strategy.

In essence, I want to apply a middleware routine using app.use('*', ensureAuthenticated, ...), where ensureAuthenticated checks if the session exists and is authenticated or the http credentials are provided).

The other examples of mixing twitter, oath and other passport strategies does not really apply since they are all based on mapping disctinct routes whereas stateless auth like basic and digest authenticate at every request.

Thanks for any advice,

Nicolas

Yes, you can setup multiple strategies:

passport.use(new LocalStrategy(...));
passport.use(new BasicStrategy(...));

and use both of them when authenticating:

app.post('/login', passport.authenticate(['basic', 'local']), ...

just specify an array of strategy names. Authentication attempts them in order, succeeding if any succeed and failing if they all fail.

If you call .isAuthenticated does it also check Basic automatically? One would think it should, or at least I do, lol.

To give some context, I enable Basic on local dev environment to quickly test against multiple API calls, while my production has Auth turned off. But still, shouldn't isAuthenticated check if Basic has been setup, and thus check if the session does not exist via a Local/Facebook/Twitter/etc.

I was struggling with this issue too. In my case, I wanted the api router to support both:

  • Session authentication for ajax usage on client-side webpages
  • Sessionless basic authentication on programmatic clients

As you've probably experienced already, isAuthenticated checks only for the existence of the user property (just grab the source), so it's only useful when the user has already been set by a previous session. If you want to check for a user session (maybe with a pre-existing local strategy), but fall back to basic authentication, you can create this middleware:

var ensureAuthenticated = function ensureAuthenticated(req, res, next) {
  console.log('ensureAuthenticated');  
  if (req.isAuthenticated()) {
    return next();
  }
  passport.authenticate('basic', {session: false})(req, res, next);
};

Be aware of the dangers of overloading the authentication strategy - subsequent basic requests will keep the local credentials, which can be head-scratching. But it could be helpful during development -- or if you do expect basic and local authenticating users to be distinct.