Node.JS/Passport-CI-OIDC - Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader
Node.JS/Passport-CI-OIDC - Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader
我一直在尝试使用 passport-ci-oidc 和 node.js 执行一些身份验证。在以前的变体中,我使用了 passport-idaas-openidconnect 并且对我来说一切正常。现在我收到以下错误:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/response.js:718:10)
at app.use (/Users/LSBTUser1/ibm/iERPedia/app.js:219:7)
at Layer.handle [as handle_request] (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/index.js:312:13)
at /Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/index.js:330:12)
at next (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/index.js:271:10)
at urlencodedParser (/Users/LSBTUser1/ibm/iERPedia/node_modules/body-parser/lib/types/urlencoded.js:91:7)
at Layer.handle [as handle_request] (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/layer.js:95:5)
即使我将删除错误消息中提到的行 - 我也会收到同样的错误,但不会提及我的代码的任何地方(仅“/node_modules/serve-static/node_modules/send/index.js”中的错误)。我的代码:
function doAuth(req, res, next) {
if (req.originalUrl.indexOf('/auth/sso/callback') === 0 || req.originalUrl === '/login') {
return next();
}
if (!req.isAuthenticated()) {
callback_url = req.originalUrl;
res.redirect('/login');
}
return next();
}
if (process.env.iERPediaAPIhost) {
iERPediaAPIhost = process.env.iERPediaAPIhost;
REQUEST_TIMEOUT = process.env.REQUEST_TIMEOUT ?
Number(process.env.REQUEST_TIMEOUT) :
REQUEST_TIMEOUT;
FILE_SIZE_LIMIT = process.env.FILE_SIZE_LIMIT || FILE_SIZE_LIMIT;
MAIL_URL = process.env.MAIL_HOST_URL || MAIL_URL;
iERPediaAPIport = 80;
config = {
applicationId: appEnv.app.application_id,
applicationRoute: appEnv.url,
};
// +++ START NEW BlueID ++++
const Strategy = new OpenIDConnectStrategy({
discoveryURL: process.env.BlueID_discovery_url,
clientID: process.env.BlueID_client_id,
scope: 'openid',
response_type: 'code',
clientSecret: process.env.BlueID_client_secret,
callbackURL: process.env.BlueID_callback_url,
skipUserProfile: true,
},
(iss, sub, profile, accessToken, refreshToken, params, done) => {
process.nextTick(() => {
profile.accessToken = accessToken;
profile.refreshToken = refreshToken;
done(null, profile);
});
});
app.get('/login', passport.authenticate('openidconnect'));
app.use(cookieParser());
app.use(cookiesession({
name: 'bp',
secret: 'kurkawodna',
cookie: { maxAge: 8 * 60 * 60 * 1000 }, // hours
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(Strategy);
passport.serializeUser((user, done) => {
user._json.blueGroups = [];
done(null, user);
});
passport.deserializeUser((obj, done) => {
done(null, obj);
});
}
app.use('*', (request, response, next) => { doAuth(request, response, next); });
// serve the files out of ./public as our main files
app.use(express.static(path.join(__dirname, '/dist')));
app.use('/api', proxy(`${iERPediaAPIhost}:${iERPediaAPIport}`, {
proxyReqOptDecorator: function proxyReqOptDecorator(proxyReq) {
proxyReq.headers['X-ApplicationId'] = config.applicationId;
return proxyReq;
},
reqBodyEncoding: null, // default is utf8. But with utf8 files are converted from binary to utf8.
limit: FILE_SIZE_LIMIT,
}));
app.use('/mail', proxy(`${MAIL_URL}:443`, {
proxyReqOptDecorator: function proxyReqOptDecorator(proxyReq) {
proxyReq.headers['Authorization'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
proxyReq.headers['Content-Type'] = 'application/json';
return proxyReq;
},
reqBodyEncoding: null, // default is utf8. But with utf8 files are converted from binary to utf8.
limit: FILE_SIZE_LIMIT,
https: true,
}));
app.use('/Bluepages', proxy(`${BLUEPAGES_URL}:${BLUEPAGES_PORT}`, {
proxyReqOptDecorator: function(proxyReqOpts, originalReq) {
proxyReqOpts.headers['X-IBM-Client-Id'] = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
proxyReqOpts.headers['X-IBM-Client-Secret'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
proxyReqOpts.key = [bpKey];
proxyReqOpts.cert = [bpCert];
return proxyReqOpts;
}
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
console.log('######################################################################');
console.log('# iERPedia three');
console.log(`# Uses connection to ${iERPediaAPIhost}:${iERPediaAPIport}`);
console.log('######################################################################');
function getUserDataFromBP(req) {
return {
id: req.user._json.uid,
intranet_id: req.user.id,
name: req.user._json.firstName,
surname: req.user._json.lastName,
email: req.user._json.emailAddress,
};
}
function getSendGridAuth() {
return {
user: EMAIL_USER,
api_key: EMAIL_API_KEY,
};
}
function getApplicationUrl() {
return { url: appEnv.url };
}
// enable CORS: http://enable-cors.org/server_expressjs.html
app.use((req, res, next) => {
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
next();
});
app.get('/auth/getCurrentUser', (req, res) => {
res.send(getUserDataFromBP(req));
});
app.get('/auth/getSendGridAuth', (req, res) => {
res.send(getSendGridAuth());
});
app.get('/getApplicationURL', (req, res) => {
res.send(getApplicationUrl());
});
app.get('/logout', (req) => {
req.logOut();
req.session = null;
});
app.get('/auth/sso/callback', (req, res, next) => {
passport.authenticate('openidconnect', {
successRedirect: callback_url,
failureRedirect: '/failure',
})(req, res, next);
});
app.get('/failure', (req, res) => {
res.send('Login failed. Please try again');
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});
// start server on the specified port and binding host
const server = app.listen(appEnv.port, '0.0.0.0', () => {
// print a message when the server starts listening
console.log(`server starting on ${appEnv.url}`);
});
server.timeout = REQUEST_TIMEOUT; // 5 min for uploading file
这可能是doAuth中的重定向导致的。如果中间件没有呈现任何东西,你只应该调用 next() 。这应该修复:
function doAuth(req, res, next) {
if (req.originalUrl.indexOf('/auth/sso/callback') === 0 || req.originalUrl === '/login') {
return next();
}
if (!req.isAuthenticated()) {
callback_url = req.originalUrl;
return res.redirect('/login');
}
return next();
}
还有两件事:
而不是使用
app.use('*', (request, response, next) => { doAuth(request, response, next); });
你可以简单地使用 app.use('*', doAuth);
并在文件开头设置cors和common headers(否则某些路由将没有cors)
我一直在尝试使用 passport-ci-oidc 和 node.js 执行一些身份验证。在以前的变体中,我使用了 passport-idaas-openidconnect 并且对我来说一切正常。现在我收到以下错误:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/response.js:718:10)
at app.use (/Users/LSBTUser1/ibm/iERPedia/app.js:219:7)
at Layer.handle [as handle_request] (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/index.js:312:13)
at /Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/index.js:330:12)
at next (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/index.js:271:10)
at urlencodedParser (/Users/LSBTUser1/ibm/iERPedia/node_modules/body-parser/lib/types/urlencoded.js:91:7)
at Layer.handle [as handle_request] (/Users/LSBTUser1/ibm/iERPedia/node_modules/express/lib/router/layer.js:95:5)
即使我将删除错误消息中提到的行 - 我也会收到同样的错误,但不会提及我的代码的任何地方(仅“/node_modules/serve-static/node_modules/send/index.js”中的错误)。我的代码:
function doAuth(req, res, next) {
if (req.originalUrl.indexOf('/auth/sso/callback') === 0 || req.originalUrl === '/login') {
return next();
}
if (!req.isAuthenticated()) {
callback_url = req.originalUrl;
res.redirect('/login');
}
return next();
}
if (process.env.iERPediaAPIhost) {
iERPediaAPIhost = process.env.iERPediaAPIhost;
REQUEST_TIMEOUT = process.env.REQUEST_TIMEOUT ?
Number(process.env.REQUEST_TIMEOUT) :
REQUEST_TIMEOUT;
FILE_SIZE_LIMIT = process.env.FILE_SIZE_LIMIT || FILE_SIZE_LIMIT;
MAIL_URL = process.env.MAIL_HOST_URL || MAIL_URL;
iERPediaAPIport = 80;
config = {
applicationId: appEnv.app.application_id,
applicationRoute: appEnv.url,
};
// +++ START NEW BlueID ++++
const Strategy = new OpenIDConnectStrategy({
discoveryURL: process.env.BlueID_discovery_url,
clientID: process.env.BlueID_client_id,
scope: 'openid',
response_type: 'code',
clientSecret: process.env.BlueID_client_secret,
callbackURL: process.env.BlueID_callback_url,
skipUserProfile: true,
},
(iss, sub, profile, accessToken, refreshToken, params, done) => {
process.nextTick(() => {
profile.accessToken = accessToken;
profile.refreshToken = refreshToken;
done(null, profile);
});
});
app.get('/login', passport.authenticate('openidconnect'));
app.use(cookieParser());
app.use(cookiesession({
name: 'bp',
secret: 'kurkawodna',
cookie: { maxAge: 8 * 60 * 60 * 1000 }, // hours
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(Strategy);
passport.serializeUser((user, done) => {
user._json.blueGroups = [];
done(null, user);
});
passport.deserializeUser((obj, done) => {
done(null, obj);
});
}
app.use('*', (request, response, next) => { doAuth(request, response, next); });
// serve the files out of ./public as our main files
app.use(express.static(path.join(__dirname, '/dist')));
app.use('/api', proxy(`${iERPediaAPIhost}:${iERPediaAPIport}`, {
proxyReqOptDecorator: function proxyReqOptDecorator(proxyReq) {
proxyReq.headers['X-ApplicationId'] = config.applicationId;
return proxyReq;
},
reqBodyEncoding: null, // default is utf8. But with utf8 files are converted from binary to utf8.
limit: FILE_SIZE_LIMIT,
}));
app.use('/mail', proxy(`${MAIL_URL}:443`, {
proxyReqOptDecorator: function proxyReqOptDecorator(proxyReq) {
proxyReq.headers['Authorization'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
proxyReq.headers['Content-Type'] = 'application/json';
return proxyReq;
},
reqBodyEncoding: null, // default is utf8. But with utf8 files are converted from binary to utf8.
limit: FILE_SIZE_LIMIT,
https: true,
}));
app.use('/Bluepages', proxy(`${BLUEPAGES_URL}:${BLUEPAGES_PORT}`, {
proxyReqOptDecorator: function(proxyReqOpts, originalReq) {
proxyReqOpts.headers['X-IBM-Client-Id'] = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
proxyReqOpts.headers['X-IBM-Client-Secret'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
proxyReqOpts.key = [bpKey];
proxyReqOpts.cert = [bpCert];
return proxyReqOpts;
}
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
console.log('######################################################################');
console.log('# iERPedia three');
console.log(`# Uses connection to ${iERPediaAPIhost}:${iERPediaAPIport}`);
console.log('######################################################################');
function getUserDataFromBP(req) {
return {
id: req.user._json.uid,
intranet_id: req.user.id,
name: req.user._json.firstName,
surname: req.user._json.lastName,
email: req.user._json.emailAddress,
};
}
function getSendGridAuth() {
return {
user: EMAIL_USER,
api_key: EMAIL_API_KEY,
};
}
function getApplicationUrl() {
return { url: appEnv.url };
}
// enable CORS: http://enable-cors.org/server_expressjs.html
app.use((req, res, next) => {
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
next();
});
app.get('/auth/getCurrentUser', (req, res) => {
res.send(getUserDataFromBP(req));
});
app.get('/auth/getSendGridAuth', (req, res) => {
res.send(getSendGridAuth());
});
app.get('/getApplicationURL', (req, res) => {
res.send(getApplicationUrl());
});
app.get('/logout', (req) => {
req.logOut();
req.session = null;
});
app.get('/auth/sso/callback', (req, res, next) => {
passport.authenticate('openidconnect', {
successRedirect: callback_url,
failureRedirect: '/failure',
})(req, res, next);
});
app.get('/failure', (req, res) => {
res.send('Login failed. Please try again');
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
});
// start server on the specified port and binding host
const server = app.listen(appEnv.port, '0.0.0.0', () => {
// print a message when the server starts listening
console.log(`server starting on ${appEnv.url}`);
});
server.timeout = REQUEST_TIMEOUT; // 5 min for uploading file
这可能是doAuth中的重定向导致的。如果中间件没有呈现任何东西,你只应该调用 next() 。这应该修复:
function doAuth(req, res, next) {
if (req.originalUrl.indexOf('/auth/sso/callback') === 0 || req.originalUrl === '/login') {
return next();
}
if (!req.isAuthenticated()) {
callback_url = req.originalUrl;
return res.redirect('/login');
}
return next();
}
还有两件事:
而不是使用
app.use('*', (request, response, next) => { doAuth(request, response, next); });
你可以简单地使用 app.use('*', doAuth);
并在文件开头设置cors和common headers(否则某些路由将没有cors)