2

I'm not very experienced with nginx but I know enough to get by.

Recently I came across a bug that is now resolved, but I wanted clarification as to why this would be occuring.

So I have several node applications and nginx works as a reverse proxy towards them. The webserver is setup with HTTPS and one of these applications has a login page with a mongoDB backend that it uses to persist sessions.

The location block for this application is this:

location /app/abcd {
    proxy_pass http://localhost:3003;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;

    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

I also had another application which had a similar location block but it was set to point towards the root like so:

location / {
    proxy_pass http://localhost:3002;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;

    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

My goal was if you went to app/abcd then the first app would handle the request, and anything else would be handled by the second one.

Everything seemed to be working fine except the persistence of sessions. If I tried to goto /app/abcd it would store the sessions fine but it seemed that users were losing ownership of their sessions upon every page refresh.

My NodeJS session code looked like this:

app.set('trust proxy', 1);

app.use(session({
    secret: 'secret',
    resave: false,
    saveUninitialized: true,
    proxy: true,
    cookie: {
        httpOnly: false,
        expires: false,
        maxAge: 1000000000000,
        secure: true
    },
    store: new MongoStore({
        mongooseConnection: db
    })
}));

Once I removed the block that was pointing towards location / it all started working. I don't know enough about nginx to understand what it was doing behind the scenes to break session persistence, could somebody explain to me what was happening?

user1157885
  • 1,999
  • 3
  • 23
  • 38

1 Answers1

0

What is happening here is that Nginx will pass the full path towards your Express application (NodeJS), in your case this would be /app/abcd.

However, your Express application has routes listening on only /. Let's say your backend code has the following JavaScript, which results in a 404 not found:

app.use('/', routes)

You could change your backend code (NodeJs) to match the add path, for example:

app.use('/app/abcd', routes)

OR alternatively, make Nginx strip the app/abcd section from the request. In this latter case you just need to add a trailing slash to the end of the proxy_pass section (note the extra / at the end):

proxy_pass http://localhost:3002/;

See also: https://serverfault.com/a/601366/227596

Melroy van den Berg
  • 2,697
  • 28
  • 31