Sn0wFox Sn0wFox - 3 months ago 16
Node.js Question

Clustered Nodejs server and CAS server: CORS issue

I have a Nodejs based server, which uses a middleware which basically redirects the user to a CAS to manage authentication. The CAS server responds with a ticket, and finally my Nodejs server trades the ticket for an user object with the CAS and stores it in a session.

This process works perfectly fine without cluster.

Today i wanted to clusterize my Nodejs server, using https://nodejs.org/api/cluster.html (thing that i've already done without any problem).

So instead of having:

let server = http.createServer(app);
server.listen(PORT, HOST, () => {
// Keep a track that the server has been launched
logger.log(`Server running at http://${HOST}:${PORT}/`);
});


Where everything was working fine, I now have:

if(cluster.isMaster) {

// This is the mother process

// Let's create the threads
for(let i=0; i < NB_WORKERS; i++) {
cluster.fork();
}

// When a child crash... Restart it
cluster.on('exit', (worker, code, signal) => {
logger.log("info", "A child died (PID: %s). It was killed by code or signal %s. Restarting...", worker.process.pid, dode || signal);
cluster.fork();
});
} else {
// This is a child

// Create the server, based on http
let server = http.createServer(app);
server.listen(PORT, HOST, () => {
// Keep a track that the server has been launched
logger.log(`Server running at http://${HOST}:${PORT}/`);
});
}


When i launch the server, it actually starts the server on
NB_WORKERS
threads, as expected. But when i want to access the app delivered by my Node server with my browser, i have the following error:

enter image description here

which says if you can't see:

XMLHttpRequest cannot load https://localhost:8443/cas/login?
service=http://localhost:3000. No 'Access-Control-Allow-Origin' header is
present on the requested resource. Origin 'http://localhost:3000' is
therefore not allowed access


https://locahost:8443
is were my CAS server is running, and
http://localhost:3000
is where my Node server is running.

Note that if i set
NB_WORKERS
to 1, everything works fine again.

I understand that setting 'Access-Control-Allow-Origin' header in my CAS server config would probably make everything works fine, but i don't understand why it's working with one thread and not with two or more.

What am i missing ?

Answer

I finally managed to make it work, so i post here in case someone come across a similar issue.

About Node session

As I said, my Nodejs server stores datas into a session. In this case, it was a simple express-session with the default MemoryStore since i'm still in development.

When clustering, express-session default store is NOT shared between threads. This means that requests supposed identified by the session were sometimes not, depending of which thread handled the request. This caused the authentication middleware to ask the CAS server again.

To make it work, i had to use a persistant store for my session, such as Redis.

About the CORS issue

I'm not really sure about what caused this strange issue, but here what i thought about:

  • Since my CAS server uses HTTPS protocol, some handshakes were made between both servers due to TSL (Hello, Certificate exchange, Key exchange). Maybe these were broken if not only one thread tried to do it (One makes the Hello, then the response is sent to another thread => this can't work).

    Still it's very strange, because it's very low-level, and almost none cluster Node app would work if this was not managed internally.

  • In order to make the previous handshakes work, i guess that each thread must be identified somehow. A likely way to do it is to assign a custom port to each thread: the process still run on port 3000, but each thread use a custom one to communicate.

    Maybe this was causing my issue, but I can't really tell precisely.


So, i just had to manage correctly my session store to make it work. But please let me know if i was wrong somewhere about the CORS issue.

Comments