I aim using secure flagged cookies in a node app in IIS.
I'm working on a Next.js app and also trying to deploy on IIS to meet some corporate requirements. I've already configured IIS by installing iisnode, URL rewrite module, nodejs to server and mostly followed the footsteps in this video.
SSR and static structures are just working fine. IIS already has its own SSL certificate. According to my researchs;
iisnode requests from IIS to your node app running express. The ssl connection is terminated at IIS and your node app receives an http request. When the app requires cookies over a secure connection it fails.
So when it comes to cookies with secure options, this creates issues. As I understand I need to tell node server to trust the proxy. I found a way in express but I'd like to continue using node http module and there have to be a way in my opinion since Express is just made on top of the http module. Unfortunately I wasn't be able to find any resource about it unlike this Express example.
I've found my solution by creating another custom server file which is built with express. Actually, as I mentioned, from the beginning I kind of knew that there is a way to achieve trust proxy setting with express server. But since I'm already using node http module, I did not wanted to change this structure and wanted to learn how this proxy setting could be done in this module. I was not able to find the way to do it but since I know the express.js is built upon node http module; there have to be a way.
Unfortunately either I couldn't find it or it was harder to implement then express js. I have already a development server with http module and it also reads ssl certificate etc. Instead of completely removing it, I added another file that has expressjs and proxy setting.
The following codes are not much a big deal but it might be helpful to someone because these provide custom Next.js servers that have SSL environment for development and proxy server production.
server with express & proxy
// This server file intended to use behind IIS.
const next = require("next");
const express = require('express')
const port = process.env.PORT || 3000;
const app = next({ dev: false, dir: ".", quiet: false });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.set('trust proxy', 1)
server.get("*", (req, res) => {
return handle(req, res);
});
server.listen(port, (err) => {
if (err) {
throw err;
} else {
console.log(`Server started at port ${port}`);
}
});
});
server.dev
console.log("Development mode.");
const { createServer } = require("https");
const { parse } = require("url");
const next = require("next");
const fs = require("fs");
const port = process.env.PORT || 3000;
const app = next({ dev: devMode, dir: ".", quiet: false });
const handle = app.getRequestHandler();
const httpsOptions = {
key: fs.readFileSync("./certs/cert.key"),
cert: fs.readFileSync("./certs/cert.pem"),
};
app.prepare().then(() => {
createServer(httpsOptions, (req, res) => {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
handle(req, res, parsedUrl);
}).listen(port, (err) => {
if (err) throw err;
console.log(`Port: ${port}`);
});
});