AWS API Gateway: 403 Forbidden response to preflight OPTIONS request - node.js

I am on my way to creating an API using AWS API Gateway. I have created a PUT method to perform some functionality on my database.
You can see in the image below, I have set the following as my response headers on AWS.
This is how I am making my request to React JS:
fetch('https://myawsurl.execute-api.ap-southeast-2.amazonaws.com/Dev/search', {
method: 'PUT',
headers: {
'Content-Type':'application/json',
'Access-Control-Request-Method': 'PUT',
'Access-Control-Request-Headers': 'Content-Type'
},
body: {
"searchby": JSON.stringify({"searchby":"test"}),
}
}).then(res=>res.json()).
then((data)=>this.setState({
jobs:data,
isLoading:false,
}));
Whenever I invoke the fetch, I get the following error on my chrome console:
'Access to fetch at 'https://myawsurl.execute-api.ap-southeast-2.amazonaws.com/Dev/search' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.'
From what I see I have clearly got the 'Access-Control-Allow-Origin' on my response.
I know postman works differently, but I don't any get error while making the same request on the postman.
Here is a screenshot of what response header for the same request made via postman
Strangely, The error on firefox is differently than to that of the chrome.

Seems like you already have your answer but for others browsing this post the reason for the failure is that the CORS headers were not returned by the OPTIONS method.
The browser calls this method on our behalf before calling the PUT method. This is expected behavior.
Here is api gateway's documentation on CORS
https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

Related

POST axios request blocked by fluidpay api

I'm trying to send a post request to this end point https://sandbox.fluidpay.com/api/token-auth and I'm getting this error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://sandbox.fluidpay.com/api/token-auth. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 405
When I send the request from Postman, it works. But when I try to send it using axios, I get the above error.
This is how I'm making the request using axios:
const request = await axios({method: "post", url: "https://sandbox.fluidpay.com/api/token-auth", data: {username: username, password: password}, withCredentials: false});
Shouldn't public API's be accessible to all domains?
EDIT
It looks CORS is disabled server side. If you don't control the server, you can't do much with a browser. The only way to solve the problem is using an API owned by yourself to proxy the request.
Read more here

I am trying to save data in database but facing error

Am creating a react app in which i am using api's for saving data to database but when i post request getting error
let responseData = await fetch('https://********************',
{method: 'post',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(data)});
responseData = responseData.json();```
**error**
Access to fetch at 'https://*********************' from origin
'http://localhost:3000' has been blocked by CORS policy: Request
header field access-control-allow-origin is not
allowed by Access-Control-Allow-Headers in preflight response.
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/kMxKF.png
It looks like you need to enable CORS on your server.
I assume from your tags that you are using Express.
You can use the cors npm package:
npm install cors
Then in your app:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
// The rest of your app
See the docs for more advanced usage:
https://www.npmjs.com/package/cors
I hope this helps solve your problem.
are you trying to fetch directly from https://i.stack.imgur.com? That won't work as you can see in the error. Browsers don't allow making requests to hosts that are not same origin unless explicitly allowed, which in your case is localhost. You would need to run your own server in order to fetch data from other sources. If you are already running a server on localhost you should be fine. But if you are running a server on some other host, you would explicitly need to allow localhost as an exception to CORS policy. Most server frameworks have option to set that. Just google for whatever server you are using :)
You can install Moesif Orign & CORS Changer for chrome and switch to on and it will work for you

HTTPrequest using axios results in CORS error

I build my own API which is running on port 5000. Whenever I want to make a request to it , I get the following error:
Access to XMLHttpRequest at 'http://localhost:5000/user' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I already did some research but the only thing that seems to work is a chrome extension, which isnt ideal.
Here's what i did :
const config = {
headers : {
'Content-Type' : 'application/json',
'Access-Control-Allow-Origin': '*'
}
};
Simply, browsers block responses if server does not allow CORS. So if you are using NodeJS at your API, use this library.

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Reactjs

I'm deploying my web app to heroku and use the following cors config on the client side.
const instance = axios.default.create({
baseURL: "https://myapp-backend.herokuapp.com",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "https://myapp-backend.herokuapp.com"
}
});
And on the server side
const corsConfig = {
origin: ['https://myapp.herokuapp.com', 'http://localhost:3001']
}
app.use(cors(corsConfig));
But I keep getting error: "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
Any help would be much appreciated. Sometimes the config works but sometimes it doesn't...
The custom headers on your request (some of which are misguided) have triggered a pre-flight request for the cross origin request. This means that the browser will separately send an OPTIONS request to your server to ask it if it is OK to process this request before sending the actual request.
You have a couple of choices. First, remove the custom headers that are triggering the pre-flight request. Neither Content-Type or Access-Control-Allow-Origin are appropriate for a request you are sending from the browser. Content-Type belongs to the response and the client does not get to specify anything about what origins are allowed - that's for the server to decide.
If, for some reason, you can't stop the browser from triggering the pre-flight request, then you need to explicitly add support to your server for the OPTIONS pre-flight request. You can see how to use the cors module to do that here.

AWS API Gateway returns access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response

This may seem like it's been asked a million times but I've tried adding to both my frontend (React) and backend (Lambda with Node.js):
Access-Control-Allow-Headers
Access-Control-Request-Headers
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE,PATCH,OPTIONS'
But I still get this error:
Access to XMLHttpRequest at 'https://<API-INVOKE-URL>/prod/notes' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
Here's my Lambda code to handle response:
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
};
Here's my React code to send the POST request:
createNote(note) {
return API.post("notes", "/notes", {
headers: {
"Authorization": this.state.token,
"Access-Control-Allow-Origin": "*"
},
body: {
userid: this.state.username,
noteid: 'new',
content: 'from frontend'
}
});
I've tested my Lambda function from the console and it works (able to do CRUD to DynamoDB).
I've turned on CORS for my API Gateway resources and deployed the API.
I've tried using PostMan with:
Headers:Content/Type: application/json
Authorization: <MY_TOKEN>
*With and without* Access-Control-Allow-Origin: *
and it works: the request is sent successfully from PostMan to API Gateway results in a new item in my DynamoDB.
Actually adding some data in header converts POST request to OPTIONS.
So that, it will fire to requests:
1) with OPTIONS method
2) After getting a successfull response for OPTIONS request, the actual API call will occur.
To handle CORS you should use this in the backend.
Just to throw some light to the problem. Some browsers will do a "preflight" check to your endpoint. That means that will invoke your endpoint with OPTIONS method before making the POST method call you expect. In AWS, go to API Gateway and create a new resource , check the option to Create Options, that will create the default response headers that you need to add to your endpoint.
CORS requires a direct connection between the client and server. Your browser may be blocking the connection for security reasons.
HTTP versus HTTPS
I'd also try enabling downloads on your browser.
I believe you should also add the bearer to your token in the authorization header like:
'Bearer TOKEN_VALUE'
Thank you, guys. I've upvoted your answers/suggestions. I'm sure they're helpful in most cases. I've figured out why I had that error.
My bad: I have both resources like this:
/notes/ (method: any)
/notes/{noteid} (method: any)
and the Invoke URL is literally <path>/notes/{noteid} (with the {} included in the string) in AWS API Gateway. I was assuming it'd be something like /notes/:noteid
So the frontend code should be like this:
return API.post("notes", "/notes/{noteid}", {...}

Resources