Home > Software engineering >  Node.js Express Websocket clients coming from http origin?
Node.js Express Websocket clients coming from http origin?

Time:03-25

I have a webapp that communicates to Node.js Express server using websocket.

When verifying the websocket connection, I check the ORIGIN header of the request (and a few other parameters to ensure they are legitimate)

The expected request is either "https://www.mywebsite.com" or "https://mywebsite.com"

If the ORIGIN header is not expected, we will kick the user.

Then I noticed some people can be kicked when their socket connection looks alright, but the ORIGIN is "http://mywebsite.com". We quickly checked and realise the website can be visited in http. We added a piece of redirect code like this:

const server = express() 
  .enable('trust proxy')
  .use((req, res, next) => {
      req.secure ? next() : res.redirect('https://'   req.headers.host   req.url)
  })

And now theoretically, whoever visit the http version of the website should be redirected to https.

But, even this redirection is done, we still notice people being kicked because their origin is http instead of https. Why is this so? Is there any chance that some users can never use https?

CodePudding user response:

This is the correct way to redirect to https on Heroku:

Under the hood, Heroku router (over)writes the X-Forwarded-Proto and the X-Forwarded-Port request headers. The app must check X-Forwarded-Proto and respond with a redirect response when it is not https but http.

Taken from: https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls

This is some sample code you can use:

app.use((req, res, next) => {
  if (req.header('x-forwarded-proto') !== 'https') {
    res.redirect(`https://${req.header('host')}${req.url}`)
  } else {
    next()
  }
})

The reason your code doesn't work is that Heroku does SSL termination for you and serves the certificates this means the connection between the Heroku router and your Node.js server is insecure and req.secure returns false: https://devcenter.heroku.com/articles/http-routing#routing
Correction: Cause you set trust proxy this means req.protocol will be set to https and req.secure will return true so your code will work.

  • Related