Search code examples
javascriptexpressauthenticationproxyhttp-proxy

Authentication middleware blocks OPTIONS preflight request due to custom header absence


I have a React application using axios as HTTP library, express server that uses http-proxy-middleware package and API express server that contains APIs.

React application should communicate with API server through proxy authentication server like this:

Communication between client and API server goes through proxy server

Within my React application I created this test method:

testReq(){
    axios.get('http://localhost:5000/applicationData/checkMe', {
      withCredentials: true,
      headers: {
        'x-access-token': '...'
      }
    })
    .then(response => console.log(response.status))
    .catch(e => console.log(e))
  }

This is how my proxy method looks like:

server.use('/applicationData', authenticate, proxy({
    target: 'http://localhost:4000',
    changeOrigin: false,
    onProxyReq(proxyReq, req) {
      // proxyReq.setHeader('x-access-identity-email', req.decodedToken.email)
    },
  }))

and this is authenticate middleware function used above:

module.exports = (req, res, next) => {
  const token = req.headers['x-access-token']
  console.log('token', token)
  if (token) {
    verifyToken(token, global.config.secret).then((verificationResponse) => {
      const { decoded, message } = verificationResponse
      if (!decoded) return res.status(401).json({ message })
      req.decoded = decoded
      return next()
    })
    .catch((err) => {
      console.error(err)
      res.status(500).json({ message: 'Internal error' })
    })
  } else return res.status(401).json({ message: 'Missing authentication token' })
}

I enabled CORS on both API and Proxy servers like this:

server.all('/*', (req, res, next) => {
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
    res.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, x-access-token')
    res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')
    res.header('Access-Control-Allow-Credentials', 'true')
    next()
  })

The problem is that I get this response when request is sent:

enter image description here

I assume it's due to authentication middleware trying to access x-access-token header from OPTIONS request which doesn't exist and therefore returns 401. If I remove authentication middleware from proxy method then requests go through.

How do I make x-access-token present in OPTIONS requests? Or else, what is the proper way to handle this situation?


Solution

  • in facebook not allowing to paste code not sure, why, so pasting here:

    in your middleware missing is (for options part as you have commented):

    if (req.method == 'OPTIONS') {
      res.send(200);
    }
    else {
      next();
    }
    

    for error part, as you have said authentication triggering before cors part, so you may have to set that code before authentication (security part I am not much sure)