After upgrading from Passport 0.5.2 to 0.6.0, our application behaves weird. I tried to isolate the code that is broken. Unfortunally, I wasn't able to reproduce it in my sample. But it should give an idea what our larger app is doing. Why might the await not "await"... I see the next midddleware called before the one with the async/await finishes. So of course we get the error "Error: Cannot set headers after they are sent to the client" because it continues on and then we try to redirect.
const express = require('express');
const app = express();
const session = require('express-session');
const port = 8080;
const passport = require('passport');
const SamlStrategy = require('@node-saml/passport-saml').Strategy;
const bodyParser = require("body-parser");
const cookieParser = require('cookie-parser');
app.use(bodyParser.json({ type: ['text/plain', 'application/json'] }));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
app.use(passport.initialize());
app.use(passport.session());
const samlStrategy = new SamlStrategy(
{
"path": "/login/callback",
"entryPoint": "https://xxxx.oktapreview.com/app/xxxxx1/XXX/sso/saml",
"issuer": "xxx",
"cert": "XXXXXXXX"
},
(profile, done) => {
return done(null, profile);
}
);
passport.use(samlStrategy);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
app.get('/login', (req, res, next) => {
const destination = '/';
passport.authenticate('saml', {
additionalParams: { 'RelayState': JSON.stringify({ destination }) },
failureRedirect: '/login'
})(req, res, next);
});
app.use('/login/callback',
passport.authenticate(
'saml', {
failureRedirect: '/login'
}
),
async (request, response, next) => {
console.log("in second")
const {
user: { firstName, emailAddress, emailaddress, nameID },
body: { RelayState: relayState = '{}' } = {}
} = request;
const email = emailAddress || emailaddress || nameID;
const user = {
firstName,
email,
nameID
};
// store a new user object
request.session.user = user;
try {
console.log("in try");
await new Promise((resolve, reject) => setTimeout(resolve, 13000));
console.log("after promise");
} catch (error) {
console.log("in catch", error);
// swallow it
}
const destination = '/';
console.log("before redirect");
response.redirect(destination);
console.log('after redirect');
},
( request, response, next) => {
console.log("don't come down here, you redirected!");
next();
}
);
app.get('/', (req, res) => {
res.send('Hello World!')
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
});