I would have solved this issue by using jQuery $.ajax function but in this case jQuery is not option. Instead I am going with CORS request. I feel there is something wrong with the webserver that is responding to the request and I am having a hard time figuring out what the issue is.
Here is my code for creating the CORS request
var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', url, true);
httpRequest.setRequestHeader( 'Access-Control-Allow-Origin', '*');
httpRequest.setRequestHeader( 'Content-Type', 'application/json' );
httpRequest.onerror = function(XMLHttpRequest, textStatus, errorThrown) {
console.log( 'The data failed to load :(' );
console.log(JSON.stringify(XMLHttpRequest));
};
httpRequest.onload = function() {
console.log('SUCCESS!');
}
Here is the console.log error:
XMLHttpRequest cannot load
http://test.testhost.com/testpage. Request header field
Access-Control-Allow-Origin is not allowed by
Access-Control-Allow-Headers.
Here are the header information:
> Remote Address:**.**.***.**:80 Request
> URL:http://test.testdomain.com/testpage Request
> Request Method:OPTIONS
> Status Code:200 OK
Request Headers:
OPTIONS /content-network HTTP/1.1
Host: test.testhost.com
Connection: keep-alive
Cache-Control: no-cache
Pragma: no-cache
Access-Control-Request-Method: POST
Origin: http://test.testdomain.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Access-Control-Request-Headers: access-control-allow-origin, content-type
Accept: */*
Referer: http://test.testdomain.com/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Response Headers:
HTTP/1.1 200 OK
Date: Thu, 14 Aug 2014 20:17:25 GMT
Server: Apache
Last-Modified: Thu, 14 Aug 2014 20:17:25 +0000
Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0
ETag: "1408047445"
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Vary: Accept-Encoding
Content-Encoding: gzip
Access-Control-Allow-Headers: origin, x-requested-with, content-type
Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
Content-Length: 6117
Connection: close
Content-Type: text/html; charset=utf-8
Your server's response allows the request to include three specific non-simple headers:
Access-Control-Allow-Headers:origin, x-requested-with, content-type
but your request has a header not allowed by the server's response:
Access-Control-Request-Headers:access-control-allow-origin, content-type
All non-simple headers sent in a CORS request must be explicitly allowed by the Access-Control-Allow-Headers response header. The unnecessary Access-Control-Allow-Origin header sent in your request is not allowed by the server's CORS response. This is exactly what the "...not allowed by Access-Control-Allow-Headers" error message was trying to tell you.
There is no reason for the request to have this header: it does nothing, because Access-Control-Allow-Origin is a response header, not a request header.
Solution: Remove the setRequestHeader call that adds a Access-Control-Allow-Origin header to your request.
Remove:
httpRequest.setRequestHeader( 'Access-Control-Allow-Origin', '*');
... and add:
httpRequest.withCredentials = false;
In addition to your CORS issue, the server you are trying to access has HTTP basic authentication enabled. You can include credentials in your cross-domain request by specifying the credentials in the URL you pass to the XHR:
url = 'http://username:password#test.testhost.com/testpage'
Enable CORS on backend server
or
add chrome extensions
https://chrome.google.com/webstore/search/CORS?utm_source=chrome-ntp-icon and make ON
We see this a lot with OAuth2 integrations. We provide API services to our Customers, and they'll naively try to put their private key into an AJAX call.
This is really poor security. And well-coded API Gateways, backends for frontend, and other such proxies, do not allow this. You should get this error.
I will quote #aspillers comment and change a single word: "Access-Control-Allow-Origin is a header sent in a server response which indicates IF the client is allowed to see the contents of a result".
ISSUE: The problem is that a developer is trying to include their private key inside a client-side (browser) JavaScript request. They will get an error, and this is because they are exposing their client secret.
SOLUTION: Have the JavaScript web application talk to a backend service that holds the client secret securely. That backend service can authenticate the web app to the OAuth2 provider, and get an access token. Then the web application can make the AJAX call.
Related
This has been causing me some issues for a while now. I have a set of apis set up - when I make a POST request to them I get all the required response headers in postman.
Access-Control-Allow-Credentials →true
Access-Control-Allow-Headers →*
Access-Control-Allow-Methods →GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin →*
However my basic http.post fails in my Angular application as its sending in an OPTIONS preflight request. But the response doesn't seem to add up right. Here are the headers of request sent and the response recieved in the console:
REQUEST
Host: ...
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,ur;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: http://localhost:4200
Connection: keep-alive
RESPONSE
HTTP/1.1 401 Unauthorized
Server: nginx/1.15.7
Date: Thu, 20 Dec 2018 15:45:49 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 61
Connection: keep-alive
X-Powered-By: Express
ETag: W/"3d-q6cGyOBiwGshxQdcFRrR1zCi7Cw"
The error message in the console is: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
But thats not true - the server is set up to send all correct headers.
Here is my code:
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json' })
};
...
login(email:string, password:string){
var url = environment.url;
let data = {email:email, password:password};
let response = this.http.post(url, (data), httpOptions);
return response;
}
I need to send data as application/json content type plus all the required headers are set up on the server. So what exactly is the problem here?
The OPTIONS request is not related with Angular, it is triggered by your browser because you are accessing a resource from another domain.
So the solution is to add the Access-Control headers to the OPTIONS verb on your Express server, as they are not present in the response headers you pasted.
Your server response was:
HTTP/1.1 401 Unauthorized
Server: nginx/1.15.7
Date: Thu, 20 Dec 2018 15:45:49 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 61
Connection: keep-alive
X-Powered-By: Express
ETag: W/"3d-q6cGyOBiwGshxQdcFRrR1zCi7Cw"
You wrote
...thats not true - the server is set up to send all correct headers.
Which clearly shows what you wrote is not valid.
Your server response is missing a header:
Access-Control-Allow-Origin: *
Which will make your statement valid again.
What is your Angular running URL? http://localhost:4200 ? And your API endpoint address?
"Cross-Origin Request Blocked" that means the http request was sending by a Unauthorized URL (sometimes your local dev angular url is localhost, but API is different domain,like: http://firebase/api. that case, the API treat your localhost is Unauthorized domain).
For this issue, you need to set your API's CORS to allow accepting the http request from your localhost.
Hope I can help, thanks for any input.
I'm trying to make a GET/POST request with fetch in service worker file,
but it sends only OPTIONS request and not sending my original request.
below is my code:
fetch('http://cross-origin-server/controller/function',{
headers: {
"x-app-header": 'app'
},
"mod":"no-cors"
}).then(function(response) {
console.log(response);
});
Here are the request and response headers :
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-GB,en-US;q=0.9,en;q=0.8
Access-Control-Request-Headers:x-custom-header
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:192.168.1.215
Origin:http://localhost:3000
Response Header
Access-Control-Allow-Headers:Content-Type, Content-Length, Accept-Encoding, Authorization,Cache-Control, x-custom-header, x-requested-with
Access-Control-Allow-Methods:GET, OPTIONS
Access-Control-Allow-Origin:*
Cache-Control:no-store, no-cache, must-revalidate
Connection:Keep-Alive
Content-Length:21
Content-Type:text/html; charset=UTF-8
I am not able to understand why my original request is not sending.
I have allowed all origins from my server side (Access-Control-Allow-Origin:*).
Please help, Thanks in advance
Edit:
The problem is "real request is not sending" after preflight(OPITONS) request is complete.
Service workers will only work with traffic served over https:// (with a limited exception for same-origin http://localhost requests). Your example shows that you're making a request against http://cross-origin-server, which, while obviously not a real URL, makes it seem like you're using http://.
This question already has answers here:
Response to preflight request doesn't pass access control check Laravel and Ajax call
(1 answer)
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
(11 answers)
Closed 5 years ago.
I'm trying to send a custom header within a fetch call, but it seems that the headers aren't being sent for some reason. I found some questions that seemed to indicate that 'cors' mode needs to be set as a fetch option, but I tried that and it hasn't made a difference.
In the console I'm getting this error:
Fetch API cannot load http://localhost:8000/GroupRoutePermission. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8082' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
However if I remove the x-api-key header from my fetch request, I don't get any CORS console error and get a JSON response just fine -- my JSON with error that says api key is not set (as expected).
I've also hit my endpoint with Postman with x-api-key set, and it works fine. Strangely enough I've ripped the below code out of a previous project of mine, and in that project the custom header gets sent just fine (even without cors mode), so I'm at a loss as to what else to try.
let apiKey = ""
if (typeof localStorage.apiKey != 'undefined')
apiKey = localStorage.apiKey
else
window.location = "/login"
console.log(apiKey)
fetch(url,{
credentials: 'include',
mode: 'cors',
headers: new Headers({
'Content-Type': 'text/plain',
'x-api-key': localStorage.apiKey
})
})
Chrome Network tab Request Headers:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8,fr-CA;q=0.6,fr;q=0.4,en-CA;q=0.2
Access-Control-Request-Headers:x-api-key
Access-Control-Request-Method:GET
Cache-Control:max-age=0
Connection:keep-alive
Host:localhost:8000
Origin:http://localhost:8082
Referer:http://localhost:8082/lists/ResearchTrial
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.90 Safari/537.36
Response Headers with X-Api-Key sent:
HTTP/1.1 200 OK
Host: localhost:8000
Connection: close
X-Powered-By: PHP/5.5.38-4+deb.sury.org~xenial+1
Allow: GET,HEAD
Cache-Control: no-cache
Content-Type: text/html; charset=UTF-8
Date: Tue, 12 Sep 2017 19:30:58 GMT
Response Headers if I remove X-Api-Key in request:
HTTP/1.1 200 OK
Host: localhost:8000
Connection: close
X-Powered-By: PHP/5.5.38-4+deb.sury.org~xenial+1
Access-Control-Allow-Origin: http://localhost:8082
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Content-Length, Accept- Encoding, X-Api-Key
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
Cache-Control: no-cache
Content-Type: application/json
Date: Tue, 12 Sep 2017 19:28:29 GMT
Please help!
I've ripped the below code out of a previous project of mine, and in that project the custom header gets sent just fine (even without cors mode), so I'm at a loss as to what else to try.
Was that project also making cross-domain requests?
My guess is that the API will send cors headers when auth fails, but will not send the headers when auth succeeds. This doesn't affect Postman, which doesn't have to worry about cors.
You should be able to confirm this in Postman by sending an authenticated request and checking the response headers.
I am using angular js to consume a rest service . The rest api does return required headers but I get
Response for preflight has invalid HTTP status code 401
and in mozilla I get
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://testurl.com:8081/v1/users. (Reason: CORS preflight channel did not succeed).
error
API header returns gives
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Access-Control-Allow-Headers: x-requested-with, Authorization
Access-Control-Expose-Headers: x-requested-with
Access-Control-Max-Age: 3600
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
X-Application-Context: application:8081
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 05 Jan 2016 14:57:20 GMT
Below is http request
$http({
method: 'post',
url: 'http://testurl.com/v1/users',
data : data
}).then(function successCallback(response) {
object.sucess=true;
object.massage=response;
console.log('success');
}, function errorCallback(response) {
object.sucess=true;
object.massage=response;
});
Am I doing something wrong or the problem is in header .
As I read your problem i have also faced this problems and this problem can be resolved from server side as well from client side also by creating proxy server. In server side you need to allow the ip of your system.
Usually their are 3 solutions as i know.
1).
Example: As What i do while creating web service in NodeJs(API):
res.setHeader('Access-Control-Allow-Origin', 'http://hostname.com');
// Request methods you wish to allow
// You can write * also for allowing to access that url from all systems which is not done usually for security purposes
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
Then you can run get as well as post request too.
2). You can also create proxy server to handle that post and put reuests so that communication to that api will be constant
3). You can install CORS plugin in your chrome browser and enable it and you can query to the server side.
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?utm_source=chrome-ntp-icon
I found the solution . It was missing preflight OPTIONS. I had to add those in my back end . Now it works fine .
You have put Authorization as an allowed header. This is incorrect, instead you need to add Access-Control-Allow-Credentials which will allow this header.
This separate setting controls the browser sending cookies as well as Authorization header
i am including JS on domain1 form domain2
<script type="text/javascript" src="http://www.domain2.com/script.js"></script>
that script doesn onload and on button click a JSONP request to domain2
$.getJSON( 'http://www.domain2.com/process?callback=?',
function(data){
if ( data ) processData( data );
}
);
and then displaying the data on domain1.
So here is my problem:
The getJSON request doesnt send cookies to the domain2.
The weirdest thing is that it does send the cookies half a day and the other half not. :-)
This is how the request looks like when it doesnt work:
Request details
GET /ajax/embed-user-library?detail=98&callback=jsonp1312398534998 HTTP/1.1
User-Agent: Opera/9.80 (Windows NT 6.1; U; en) Presto/2.9.168 Version/11.50
Host: www.floowie.com
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: en,sk-SK;q=0.9,sk;q=0.8
Accept-Encoding: gzip, deflate
Referer: http://www.sokker.cz/en/test2
Connection: Keep-Alive
Response details
HTTP/1.1 200 OK
Date: Wed, 03 Aug 2011 19:06:51 GMT
Server: Apache/2.2.16 (Debian)
X-Powered-By: PHP/5.3.5-0.dotdeb.1
Set-Cookie: SESSID=64292b70dc28d7c6c9f13f70070353d8; path=/; domain=.floowie.com
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Length: 34
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: application/json
And this when it works(nothing changed in the scripts):
Request details
GET /ajax/embed-user-library?detail=99&test=1&callback=jsonp1312398534999 HTTP/1.1
User-Agent: Opera/9.80 (Windows NT 6.1; U; en) Presto/2.9.168 Version/11.50
Host: test1.floowie.com
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: en,sk-SK;q=0.9,sk;q=0.8
Accept-Encoding: gzip, deflate
Referer: http://www.sokker.cz/en/test2
Cookie: __utma=254918925.1489796832.1301725317.1312260335.1312298033.44; __utmz=254918925.1312298033.44.11.utmcsr=sokker.cz|utmccn=(referral)|utmcmd=referral|utmcct=/en/test2; lang=en; FLWSESSID=ddd1bc696f83f5a70b5f0f3ae30b4691; __utma=121955676.1030804516.1282595153.1312390656.1312397285.194; __utmb=121955676.8.10.1312397285; __utmc=121955676; __utmz=121955676.1312397285.194.21.utmcsr=floowie.crmserver.cz|utmccn=(referral)|utmcmd=referral|utmcct=/index.php
Connection: Keep-Alive
Response details
HTTP/1.1 200 OK
Date: Wed, 03 Aug 2011 19:07:45 GMT
Server: Apache/2.2.16 (Debian)
X-Powered-By: PHP/5.3.5-0.dotdeb.1
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Length: 20
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: application/json
Did someone see such a behaviour?
Is it solvable?
Thank you
If you want to use AJAX petitions over different domains/subdomains you have to implement Cross Origin Requests.
References:
http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
https://developer.mozilla.org/en/http_access_control
Examples:
http://arunranga.com/examples/access-control/
Your server needs to send this headers:
Access-Control-Allow-Origin: test1.floowie.com
Access-Control-Allow-Credentials: true // allow cookie/session credentials
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
You can return the Access-Control-Allow-Origin globally or set specifically dependent of your input Origin ($_SERVER['HTTP_ORIGIN']) request header. Also apply for Access-Control-Allow-Methods.
You must implement the OPTIONS petition. Before the first AJAX call, modern browsers call that URL with an OPTIONS method to retrieve the above headers.
Ok this is the first part, the second is with jQuery. Read very carefully this page: http://api.jquery.com/jQuery.ajax/
You will need to add some options to every AJAX call, you can do it globally:
$(document).ajaxSend(function (event, xhr, settings) {
settings.xhrFields = {
withCredentials: true
};
});
Or specific:
$.ajax({
url: a_cross_domain_url,
xhrFields: {
withCredentials: true
}
});
This issue made me lose many hours... hope it helps.
Note that you won't need to set your cookie domain as ".floowie.com" if you want.
You must properly implement CORS requests with credentials to send and receive cookies via Ajax. See developer.mozilla.org, specifically under the section titled "Requests with credentials."
First off, here is a simple CORS Ajax request with credentials, using jQuery 1.5.1+:
$.ajax({
url: "http://www.domain2.com/process",
xhrFields: {
withCredentials: true
}
}).done(function (data) { console.log(data); });
Note the withCredentials flag in the xhrFields. This flag tells the browser to send cookies with the request for the external domain, not the origin domain. In your case, cookies for www.domain2.com will be sent, and you will have access to them server-side.
On the server-side, you need to add certain headers to the response:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: www.domain1.com
Important: requests with credentials cannot set the Access-Control-Allow-Origin header to global (Access-Control-Allow-Origin: *). It must specify domains (Access-Control-Allow-Origin: www.domain1.com).
It's obviously better if you specify a domain for the Access-Control-Allow-Origin header. But if you don't know or care where the CORS request is coming from, you could use the Origin header from the request and simply set the Access-Control-Allow-Origin header of your response to that. In C#, this is how we did this:
this.Response.AddHeader("Access-Control-Allow-Origin", this.Request.Headers["Origin"]);
After doing all of this, cookies that you set server-side will be sent back with the response, and the browser will be able to properly handle them and insert them into the browser's cookie store for www.domain2.com. And any subsequent CORS requests you send will send these cookies in the request as well.
If you are sending a request other than with the GET, POST, or HEAD methods, you will need to implement Preflighted requests (see under section titled "Preflighted requests"):
Unlike simple requests (discussed above), "preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
Side-note about IE8 and IE9:
The Ajax call above will fail in IE8 and 9. I included the JS file from MoonScript/jQuery-ajaxTransport-XDomainRequest on my page, and this automagically allowed CORS requests to work in those old IE versions. But sadly, the XDomainRequest object that MS created for IE8 and 9 does not allow cookies to be sent or received. (see this MSDN blog post for more information)
You have different hosts. In the first example the host is "Host: www.floowie.com". In the second it is "Host: test1.floowie.com".
I'm guessing that the cookies are originally set by 'test1.floowie.com' and you haven't specified that they should be available to '.floowie.com' (i.e. the whole domain and all subdomains).
Can you post the code that sets the cookies in the first place?
If you get this fixed, it should at least show consistent behaviour. However, IE will probably still not pass cookies across subdomains. That's what I'm wrestling with at the moment, which is how I can across your question.