I am struggling with this issue today as I am implementing a cross-site API call. The worst thing is it works well from my local environment but once on heroku, it fails with the following error:
XMLHttpRequest cannot load https://restcountries.eu/rest/v1/all. Request header field X-XSRF-TOKEN is not allowed by Access-Control-Allow-Headers in preflight response.
Here is the function triggering the call:
let observable = this._http
.get(GEO_API_URL + query)
.map(response => response.json())
.do(val => {
this.cache = val;
observable = null;
})
.share();
return observable;
Any idea ?
Thanks.
Had the same issue.
In my case the reason was that in my Chrome cookies was saved X-XSRF-TOKEN field. And somehow Chrome added header 'Access-Control-Request-Headers: x-xsrf-token' to OPTION request. In Firefox the same page works fine, in incognito mode Chrome - too.
So I've just delete this cookies field (X-XSRF-TOKEN) and that's all.
In my case I had to add the 'x-xsrf-token' value to 'Access-Control-Allow-Headers' header:
header('Access-Control-Allow-Headers: Content-Type, x-xsrf-token')
see AngularJS: POST Data to External REST API
I cleared cookies, this solved problem.
this helped me in java (expose the headers and then include in the allow headers). This will then show in your HttpResponse object:
response.addHeader("Access-Control-Expose-Headers", "header1");
response.addHeader("Access-Control-Expose-Headers", "header2");
response.addHeader("Access-Control-Expose-Headers", "header3");
response.addHeader("Access-Control-Allow-Headers", "Origin, header1, header2, header3, X-Requested-With, Content-Type, Accept");
The reason is that x-xsrf-token keyword is not in response header Access-Control-Allow-Headers.
I solved this problem in java using following solution:
rsp.setHeader("Access-Control-Allow-Methods", "GET,HEAD,POST,OPTIONS,PUT,DELETE,TRACE,CONNECT");
rsp.setHeader("Access-Control-Allow-Headers", "cache-control,content-type,hash-referer,x-requested-with, x-xsrf-token");
if ("OPTIONS".equals(req.getMethod())) {
rsp.setStatus(HttpServletResponse.SC_OK);
return;
}
Related
I'm developing a webapp angular-springboot with some other people, and to a few of those certain requests of the app are blocked by the cors with this error:
Access to XMLHttpRequest at 'https://localhost:8443/api/contratto/update' from origin 'http://localhost:4200' 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
so I have researched what a preflight request is and I've added this method to the controller:
#RequestMapping(value = "/update",method = RequestMethod.OPTIONS)
public ResponseEntity<String> preFlightHandler(){
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("Access-Control-Allow-Origin",
"https://localhost:8443");
return ResponseEntity.ok()
.headers(responseHeaders)
.body("gggg");
}
but it never even gets executed, how do I create a method mapped specifically for preflights?
didn't make a method mapped for that but I solved the error, Im' using the WebSecurityConfigurerAdapter and in the method configure(HttpSecurity http) I added the line
http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
I have backend API which was accessible with GET, but couldn't be successful with POST, due to PREFLIGHT issue, which incurred CORS blockage.
Thus, in this site,
https://newbedev.com/http-request-from-angular-sent-as-options-instead-of-post#:~:text=HTTP%20request%20from%20Angular%20sent%20as%20OPTIONS%20instead,is%20allowed%20from%20a%20particular%20domain%20as%20follows%3A
I have found that, you just simply play with OPTIONS method, which your browser calls to backend for before "ACTUAL" call. this is called Preflight request.
It uses OPTIONS method instead of get/post/put. Thus, this might be of help.
If you use Node Js Server:
if (req.method == "OPTIONS")
{
res.writeHead(200, {"Content-Type": "application/json"});
res.end();
}
With PHP, I use this code:
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header("HTTP/1.1 200 ");
exit;
}
These are my headers in PHP:
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Max-Age: 3600");
header("HTTP/1.1 200");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Authorization, X-Requested-With, Origin");
Note the OPTIONS method in the headers.
If you use other language, that might be easy for you using this concept.
That's it.
I am using Microsoft.AspNet.WebApi.Cors to support cross origin request as per this
https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
My web apis are configured to use windows authentication and every request coming from angular has withCredentials set to true. Everything is working with HTTP GET but with PUT request sends preflight request which in getting unauthorised. My question is does Microsoft.AspNet.WebApi.Cors support configuration of OPTION request.
Put this in your Global.asax.cs
(I'm sure you either found a solution or gave up, but this is the link that I found on Google while looking for a solution to this.)
protected void Application_BeginRequest()
{
if (Request.HttpMethod == "OPTIONS")
{
Response.StatusCode = (int)HttpStatusCode.OK;
Response.AppendHeader("Access-Control-Allow-Origin", Request.Headers.GetValues("Origin")[0]);
Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
Response.AppendHeader("Access-Control-Allow-Credentials", "true");
Response.End();
}
}
I'm using Express for my website and using credential xhr. I want to request to http://example.com from http://admin.example.com or http://service1.example.com, and this is my Access-Control-Allow-Origin part in express server:
// CORS
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://*.example.com');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
next();
});
But when I try credential xhr from http://admin.example.com to http://example.com, it fails with:
Fetch API cannot load http://example.com/api/v1/authentication/signin.
Response to preflight request doesn't pass access control check: The
'Access-Control-Allow-Origin' header has a value 'http://*.example.com'
that is not equal to the supplied origin. Origin
'http://admin.example.com' is therefore not allowed access. Have the
server send the header with a valid value, or, if an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
Looks like it causes from browser didn't understood what exactly *.example.com means, and refuse the request.
I want to request from these domains:
example.com
admin.example.com
service1.example.com
service2.example.com
[anything].example.com
I'm using Fetch API for XHR, and set credentials: true. Is there a something that I missed? Any advice will very appreciate it.
I agree with Derric's comment. The other thing though is that origin headers can be spoofed, so this is not a secure solution.
app.use(function (req, res, next) {
if (req.headers.origin.endsWith('example.com')) {
res.setHeader('Access-Control-Allow-Origin', 'http://' + req.headers.origin)
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
}
next()
})
First off, IIRC; express documentation explicitly asks you not to use
lambda expression for the middlewares.
Coming to the CORS issue, a wildcard subdomain is not valid in the context. The support was added pretty recently (in May '16), and until then, the CORS header must be an exact match of the domain name.
You can however, process your req.hostname value and add that to the response header:
// CORS
app.use(function (req, res, next) {
if (req.hostname.endsWith('example.com')) {
res.setHeader('Access-Control-Allow-Origin', 'http://' + req.hostname)
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
}
next()
})
Adding another small adjustment here. We should also consider "protocol":
app.use(function (req, res, next) {
if (req.headers.origin.endsWith('example.com')) {
res.setHeader('Access-Control-Allow-Origin', req.protocol + '://' + req.headers.origin)
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
}
next()
})
All the previous answers suffer from a vulnerability, exposing the api to anyone that registers a badsiteexample.com domain name. i guess they tried to include both the main domain and subdomains in the check, but there is no need as if the api is on the main domain that would not be a cors request. and if you did need it, you should use two separate conditions for main domain and subdomains, or a regex.
req.headers.origin.endsWith('.example.com') || req.headers.origin == 'example.com'
req.headers.origin.match(/(\.|^)example\.com$/)
I'm struggling with CORS issue. I make a request from js to a different domain, the method allows cross domain request and all works fine with GET but not with POST request. Looks like OPTIONS method is called before the POST and return standard error
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
return Response.ok().entity(c).header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
.header("Access-Control-Allow-Headers", "Content-Type, x-xsrf-token, X-Requested-With, Accept, Expires, Last-Modified, Cache-Control").build();
On the client side I use angularjs
$http.post(url, data).success(...)
But also tried with
$.ajax({type:'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}...})
the same result. what else can I do to fix POST request?
Add the below code to your Angular JS application config file
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
I'm using angular to send ajax request to nodejs file, and I'm having this error,
XMLHttpRequest cannot load https://localhost:3000/SetUser. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost' is therefore not allowed access.
sending it from index.html to https://localhost:3000/SetUser, and direction what could go wrong and how can I allow that access of Access-Control-Allow-Origin?
-- edit:
I googled and I found this lines
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
but I still get the same error, this is the current app.post
app.post('/SetUser', function(req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
console.log("New user added ", req.body);
});
thanks!