Node.js : POST - Request Method: OPTIONS Status Code: 403 Forbidden
Asked Answered
T

2

9

We have the following setup :

Front end code : REACT (Hosted using express js) (lets call this www.domainA.com)
Backend        : .NET WEB API (Hosted in IIS 7.5) (lets call this www.domainB.com)

The domain of the FE app is making the request to GET data and POST data to the web api.

The GET is working perfectly, however whenever I am trying to POST data to the web API, its throwing the following error :

Request URL: http://www.domainB.com/api/postdataoperation
Request Method: OPTIONS
Status Code: 403 Forbidden

I have looked at many CORS articles and went ahead and setup HTTPResponseHeaders in IIS as follows :

Access-Control-Allow-Methods : POST,GET,OPTIONS,PUT,DELETE
Access-Control-Allow-Origin  : http://www.domainA.com

The post request from react solution is as follows :

axios.post(`http://www.domainB.com/api/postdataoperation`, {userId});
Tl answered 29/3, 2018 at 18:14 Comment(8)
So I understand this right, you're hosting a node server in IIS?Despondency
@TheIncorrigible1 sorry for missing out on details (updated) the FE is hosted on ExpressTl
What do you see in the browser console? It will give you a error telling what the issue is with the request/CORS headers. Please add that info to your question as it is critical for a soluitonTrematode
are you using csrf_token ?Gilles
Have you written the Node.js server? if yes then can you share with us the Routes sections which are accepting the GET, or POST requests. That will make it more clear that what is the problem. Moreover, you can look into the Node.js server logs, to find the exact error.Lila
@MuhammadHannan, he is running a nodejs server on domainA.com, but this is irrelevent. The "axios" library can be used either to a) make XMLHttpRequests from the browser or b) make http requests from node.js. In this case it is the first option, the "axios.post" to domainB is done from the browser, that s why he gets a preflighted request.Breebreech
Have you checked these links: github.com/axios/axios/issues/960 github.com/axios/axios/issues/191 #44746173Lila
Still another tip, may be your server is running with TLS (with https protocol), and you are only requesting to http url.Lila
B
10

The issue is that your server is not configured to respond to OPTIONS requests with the correct response status, 2xx success status.

The GET is working because it is not making a preflight request, as it meets the criteria to be a simple request as defined by the CORS documentation

On the other hand, the POST request meets the criteria to be a Preflighted request, meaning a preflight OPTIONS request should be made first.

In short, you have correctly setup the CORS response headers, but the server is not configured to respond with a 2xx response for OPTIONS method requests(commonly 200 status).

The server must respond to OPTIONS requests with a 2xx success status—typically 200 or 204.

If the server doesn’t do that, it makes no difference what Access-Control-* headers you have it configured to send. And the answer to configuring the server to handle OPTIONS requests in the right way—to send a 200 or 204 success message—depends on what server software it’s running

Borrowing the solution from this answer, do this on your backend, .NET WEB API:

In your BaseApiController.cs:

We do this to allow the OPTIONS http verb

public class BaseApiController : ApiController
  {
    public HttpResponseMessage Options()
    {
      return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
    }
}

References

Preflighted requests

response for preflight 403 forbidden

Note

Running a nodejs server on domainA.com is irrelevent. The "axios" library can be used either to a) make XMLHttpRequests from the browser or b) make http requests from node.js. In this case it is the first option, the "axios.post" to domainB is done through a XMLHttpRequest from the browser, that `s why you get a preflighted request at domainB.com.

Breebreech answered 21/4, 2018 at 20:14 Comment(0)
R
1

The answer from Jannes Botis explains well the Preflighted mechanism. I'm just adding the code I'm using to solve this issue on Node.js / Express

const express = require('express');
const app = express();

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://www.domainA.com');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
  res.setHeader(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept, Authorization'
  );
  next();
});

// All OPTIONS requests return a simple status: 'OK'
app.options('*', (req, res) => {
  res.json({
    status: 'OK'
  });
});

app.get('/', ...);

app.post('/api/postdataoperation', ...);
Rodrigo answered 27/4, 2018 at 14:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.