Home > Enterprise >  Passport.js multiple strategies for a single route. Use sessions for only one strategy
Passport.js multiple strategies for a single route. Use sessions for only one strategy

Time:09-17

I am building an API endpoint with Express, NodeJS, PassportJS, and TypeScript. I want to allow two types of authentication for this endpoint. SAML (for humans) and token for automation. For human authentication, I'm using the passport-saml strategy. For token auth I'm using passport-http basic authentication. So far my code looks like:

import session from "express-session";

const samlStrategy = getSamlStrategy();
const basicStrategy = getBasicStrategy();

app.use((req, res, next) =>
  session({
    // store sessions in db
  })(req, res, next)
);

app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser((user, done) => {
  //...
});

passport.deserializeUser((username, done) => {
  //...
});

passport.use(samlStrategy);
passport.use(basicStrategy);

const requireApiAuth: express.Handler = (req, res, next) => {
  if (req.user) {
    next();
  } else {
    res.status(401);
  }
};

const tryTokenAuth: express.Handler = (req, res, next) => {
  if (!req.user && req.headers.authorization && req.headers.authorization.indexOf("Basic") > -1) {
    passport.authenticate("basic", { session: false })(req, res, next);
  } else {
    next();
  }
};

//...
// SAML endpoints here
//...

app.use(
  "/api",
  tryServiceUserAuth,
  requireApiAuth,


The basic idea is the middleware function tryTokenAuth will check to see if a user is already present on the request. If there is, then that means a human has already logged in via SAML auth. If there is no user AND if the request specifies Basic authorization then we should use the basic strategy to authenticate. At the moment, this is working. I am able to authenticate using either strategy for the /api route.

The issue is that even though I specify {session: false} for basic authentication I'm STILL getting a session cookie sent back in the response. And a session is being recorded in my database. I don't understand what I need to configure to prevent this behavior. I do NOT want a session to be created when basic auth is used.

Is there any way to accomplish this?

CodePudding user response:

As it turns out specifying session: false in the call to authenticate only prevents passport from adding its session data to a request session. The reason a session is still being created is because my config says:

app.use((req, res, next) =>
  session({
    // store sessions in db
  })(req, res, next)
);

In order to prevent this when using basic auth I had to update to:

app.use((req, res, next) => {
  if (req.headers.authorization && req.headers.authorization.indexOf("Basic") > -1) {
    next();
  } else {
    session({
      // store sessions in db
    })(req, res, next)
  }
});
  • Related