AngularJS with CORS and custom headers - http

I am using Angular $HTTP to make a CORS request to a remote API service (SmartyStreets.com). I have set the defaults as is well-documented.
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}])
When I make a plain request with no custom headers everything works as expected.
// This works as expected
$http({method: 'get', url: $scope.addr.url, headers: {}})
However, I need to now set some additional custom headers. But setting the custom headers breaks the CORS request.
// this results in the browser 404 error:
// No 'Access-Control-Allow-Origin' header is present on the requested resource
$http({method: 'get', url: $scope.addr.url,
headers: {'x-standardize-only': 'true', 'x- include-invalid': 'true'}})
I've been trying to figure this out for a couple days now...stuck. Anyone know how to solve this problem?
Thank you!!

Your server needs to correctly respond to the OPTIONS request that the browser will make on your behalf to determine if the CORS request is valid. It needs to contain an Access-Control-Allow-Headers header with the right info in it. See: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Preflighted_requests

Related

Get CORS request works but Put CORS request fails in AWS Lambda proxy integration (.net6)

I am building a collection of lambdas with proxy integration, using AWS Serverless (SAM).
I am trying my Lambdas from a frontend I have in Blazor WASM. When a GET request is issued, then I get my results on my browser without CORS issues.
But I cannot issue a PUT request without getting the dreaded:
Access to fetch at 'https://myapi.execute-api.eu-central-1.amazonaws.com/Prod/updatevictual?userId=georanto#gmail.com&victualId=da1b2daa-3a73-425e-812e-e2f164f54507' from origin 'https://localhost:7260' 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.
If I create a dedicated OPTIONS Lambda for the PUT related end-point (as suggested here) then it works. I cannot have an OPTIONS Lambda because I intend to add authentication and the OPTIONS lambda does not work with it.
According to this it should be enough to send the headers as a response. And in the case of GET it is!
To fill in my response headers(adjusting for .net6), I set my cors by attaching the headers at the returned request thus:
private static APIGatewayProxyResponse AllowCors(this APIGatewayProxyResponse response)
{
response.Headers ??= new Dictionary<string, string>();
response.Headers.Add("Access-Control-Allow-Headers",
"Content-Type, Authorization, X-Amz-Date, X-Api-Key, X-Amz-Security-Token");
response.Headers.Add("Access-Control-Allow-Methods", "*");
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Credentials", "false");
return response;
}
I am also logging my responses in Cloudwatch and the put response after the postman request is thus:
2022-05-12T06:08:30.297Z ecffb8ac-0cd9-4626-be96-6260e7a76d47 info Responding with:[{
"statusCode": 201,
"headers": {
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Amz-Date, X-Api-Key, X-Amz-Security-Token",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "false"
},
"multiValueHeaders": null,
"body": null,
"isBase64Encoded": false}]
When I issue the request in Postman I see in the response's headers that the CORS headers are set the way they were supposed to:
So I don't think that this is a code issue.
I have also tried to put all the methods (i.e. response.Headers.Add("Access-Control-Allow-Methods", "OPTIONS, DELETE, GET, HEAD, PATCH, POST, PUT") but also didn't work.
Any other ideas what could that be?
I "think" I had the same issue but I'm not familiar with .net... in your cloudfront distribution configuration, be sure to have a caching behavior that allows for put/patch/etc. and configure in that behavior a cache policy that depends on your headers

NextJS - fetch() works only inside getServerSideProps()

My fetch() method for making api requests works only when inside getServerSideProps() method.
For example I have api call for fetching a customer cart (and it is inside getServerSideProps):
const res = await fetch(apiUrl, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + jwtToken
}
});
And it works fine, I get response from api with customer cart. But when I try to make that api call on a button click, and when I move that inside button click handle method, then I get firstly:
Access to fetch at '...' 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.
After that when I set mode to 'no-cors', then I get this:
GET ... net::ERR_ABORTED 400 (Bad Request)
So how it is possible that when inside getServerSideProps, there are no any CORS issues and everything is good, but when works on a button click then I get CORS issue and after that there is that other 'Bad request' problem.
Becuase by design browsers block the API request when the API response doesn't have Access-Control-Allow-Headers. But when you fetch the API inside getServerSideProps the the API request is made by Node.js server which doesn't check for Access-Control-Allow-Headers.
If you want to make this API request in browser then you can fix it by:
// If you can change the API code, here's an example to add the CORS headers in a netlify serverless function, this is the API response that I return from a serverless function
return {
statusCode: 200,
headers: {
/* Required for CORS support to work */
'Access-Control-Allow-Origin': '*', // you can add the domain names here or '*' will allow all domains
/* Required for cookies, authorization headers with HTTPS */
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify({
message: 'Hello from netlify'
})
}
or If your API backend is in Node.js and Express.js you can use cors npm package
if you don't have the access to change the API then try writing a wrapper API (or you can say a proxy API) that will make the API request and send it's response to you.
or If you just want the API request to happen for once only (on page load like componentDidMount) you can use the getServerSideProps.
For more detailed explanation on how to fix CORS error read
How does Access-Control-Allow-Origin header work?

HERE-maps CORS problems with Autocomplete

I want to use HERE maps autocomplete in my project.
But when a i send request like the one in documentation
this.axios.get('http://autocomplete.geocoder.api.here.com/6.2/suggest.json
?app_id={YOUR_APP_ID}
&app_code={YOUR_APP_CODE}
&query=Pariser+1+Berl
&beginHighlight=<b>
&endHighlight=</b>'
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
i get an error
OPTIONS http://autocomplete.geocoder.api.here.com/6.2/suggest.json?{...} 405
Access to XMLHttpRequest at 'http://autocomplete.geocoder.api.here.com/6.2/suggest.json?{...}' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
In Chrome developer console in network panel i check this
Provisional headers are shown
Access-Control-Request-Headers: x-auth-token, content-type
Access-Control-Request-Method: GET
I set content-type in request headers to application/json and Provisional headers changed
to Access-Control-Request-Headers: x-auth-token
Access-Control-Request-Method: GET
So if i understand right, i should set x-auth-token header. But where can i take this token?
Or may be this problem has another reason?
There's nothing about such problems in documentaion.
The problem was simple and a bit stupid.
When user authenticated in my app I added default header to axios
axios.defaults.headers.common['X-Auth-Token'] = token
so this header was sended to all requests.
But HERE-map API doesn't want this header in requests and this was the cause of the problem.
The solution was to remove this header from requests to HERE-map API.
For those who have defined by default the header :
'Content-Type': 'application/json'
You must deactivate it, there should not be any HttpHeaders on the call request to Here API services.
temporary install Allow-Control-Allow-Origin google chrome plugin .. installed then you can show top right side click on that and switch the button then refresh then again call your api and get the response.

OPTIONS HTTP method instead of GET

I am new to ember js using version 3. From a route I am using this line
this.get('store').findAll('users');
Instead of setting HTTP method GET, it is setting HTTP method OPTIONS.
Because of server is getting OPTIONS as HTTP method, server side i am getting error.
io.katharsis.errorhandling.exception.MethodNotFoundException: OPTIONS:
/users/
and in browser I am getting this error
Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.
I am having the below code in application adapter and #CrossOrigin(origins="*") on Spring Rest API side.
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
init() {
this._super(...arguments);
this.set('headers', {
'Access-Control-Allow-Origin': '*'
});
},
host: 'http://localhost:8082',
namespace: 'spring-katharsis'
});
If the request contain HTTP method GET, I think it may solve the issue.
Please help on this.

Fetch API, custom request headers, CORS, and cross-origin redirects

I need to make an HTTP GET request with custom request headers in-browser and process the result as it streams in. The Fetch API is ideal for this:
fetch('https://example.com/resource', {
method: 'GET',
headers: {
'X-Brad-Test': 'true'
},
cache: 'no-store',
mode: 'cors'
}).then((res) => {
const reader = res.body.getReader();
// etc.
});
This works quite well. Since there are custom headers, the browser pre-flights the request with an OPTIONS request to /resource. I have configured my server to respond with a 204 No Content and the following headers:
Access-Control-Allow-Headers: X-Requested-With, Range, If-Range, X-Brad-Test
Access-Control-Allow-Origin: *
The browser is happy with this, then makes a GET request, the server returns a 200 OK with the data, and the browser allows me to access the response headers and body.
The problem comes in when there is a redirect. The OPTIONS request succeeds with the 204 No Content and the same headers as before. The browser makes the correct GET request, and on the server I send a 302 with a Location: header. Chrome throws the following error:
Fetch API cannot load https://example.com/resource. Redirect from 'https://example.com/resource' to 'http://some-other-origin/resource' has been blocked by CORS policy: Request requires preflight, which is disallowed to follow cross-origin redirect.
This was unexpected, and seems nonsensical to me. I expected the browser to follow the redirect, and do another pre-flight request for this new location, but it didn't do that.
Stranger still is that I can sort of hack around this client-side. I can make an HTTP request without my custom header, figure out where I ended up after redirects by looking at the Response object, then make a second request at the new target with my custom headers. This doesn't work in all cases of course, and I'd rather not rely on this hack. I'd rather find a proper way.
Two Questions:
What is the proper way to allow the client to follow redirects? Is there some sort of Access-Control-* header I can use?
Why does this restriction exist? What security issue is prevented by not following and running pre-flight on the followed URL?
Supporting redirects to requests that require a preflight is very recent change to Fetch (which defines CORS).
https://github.com/whatwg/fetch/commit/0d9a4db8bc02251cc9e391543bb3c1322fb882f2
I believe some implementations have started adjusting their implementations, but this will take some time to reach everyone.

Resources