Issue with reading Response headers - javascript

I am trying to build a chrome extension for which i need to ping to different machines.The code which i tried with is able to read the response headers for a https site but not for http.I am new to Javascripting. Any help would be great.I understand it is a CORS issue and tried setting the headers in the client code.many forums mention it setting al the server side but where can I do in this case? Please find the code below and the plugin UI and response returned from https site in the snapshot.
Code--
url="https://www.icicibank.com/";
//url = "www.rediff.com/";
ping = new XMLHttpRequest();
ping.open("get", url,true);
//ping.setRequestHeader("Access-Control-Allow-Origin","*");
// ping.setRequestHeader("Access-Control-Allow-Credentials", "true");
ping.send(null)
ping.onreadystatechange=function() {
if (ping.readyState==4) {
alert(ping.getAllResponseHeaders());
//alertify.alert(ping.getAllResponseHeaders());
}
}
Thanks

CORS is indeed part of the server response, not the request. So you cannot "set" it on your side.
However, extensions are allowed to bypass CORS restrictions and make cross-origin requests. But for that you need to list domains you're going to connect to in manifest permissions. The user will be warned, at install time, that you'll interact with those domains.
For example, to allow requests to http://example.com and https://example.com domains regardless of CORS, you need to include in the manifest:
"permissions" : [
"*://example.com/"
],
If you can't say which sites you'll need to connect to in advance, you'll either need permissions for all urls (special permission, literally, "<all_urls>") or use Optional Permissions to request that at runtime.

Related

Intune API - CORS not enabled when uploading file to azure via link from creating mobileAppContentFile

I called https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/<id>/<LOBType>/contentVersions/<content_version_id>/files, and received the azureStorageUri from it, but when I try to upload something into it (splitting the file into chunks), I always get 403 CORS not enabled.
I add $comp=block&blockid=<base64 block id> to the received uri.
My header is:
'x-ms-block-type': 'BlockBlob'
The exact error I receive is:
<Error>
<Code>CorsPreflightFailure</Code>
<Message>CORS not enabled or no matching rule found for this request.
RequestId:ce3ea3a7-f01e-0068-24b5-2c0795000000
Time:2018-08-05T12:10:00.6698414Z</Message>
<MessageDetails>No CORS rules matches this request</MessageDetails>
</Error>
Seeing as I always get the CORS issue, I tried enabling it by following this page, but, when making the request, again I receive the same CORS error.
I'm running it in my browser, if it's any help.
I'm kinda stuck and don't know how to proceed now. I'd be happy for any help. Thanks! :)
Edit: When I make the same request via Postman, it works just fine.
I'm kinda stuck and don't know how to proceed now
If you want to send a cross-origin request successfully, the request must match the CORS configuration including the request origin, headers & response headers. By default, CORS is disabled for each service. You could add the CORS setting for storage service. We could get more information about CORS from this article.
Note: CORS is not supported for Premium Storage accounts.
We could set it from Azure portal.
You can also use the wildcard character '*' to allow all origin domains to make requests via CORS.

CORS request blocked in locally opened html file

I've started to write a HTML file which displays data with JavaScript. Since it shall be done as easy as possible I don't want to run nodejs oder any other local http server. I've just opened the HTML file in a browser (url is file:///home/visu/index.htm).
Everything is fine, till a jquery ajax request to a online API is done in the index.htm. The browser blocks the request with the message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://x.x.x.x. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)."
How can I get rid of the problem without starting a local http server?
A possible solution is to start the browser with some "no security flags" or disable CORS with plugins, but this I've to do manually all the time so I don't like it.
When your browser will perform an AJAX request to a different server than the one hosting the current page, it first sends an OPTIONS HTTP message. In that message it sends the following header:
origin: http://my-web-server.com
And the backend server will respond with:
access-control-allow-origin: http://my-web-server.com
But, when you don't have a webserver, there is no address for your browser to put in that origin header. That's why your browser disallows you to do any AJAX request from a local file (maybe you can disable the browser's CORS security as someone mentioned in the comments, but that can put you at risk of malicious sites).
Another option
You can tell your browser to allow to connect from localhost to a backend if you change your backend to return the following header:
access-control-allow-origin: https://localhost:8888
And, you also need to tell your localhost server to serve your page in HTTPS instead of HTTP. Once both conditions are met, CORS validations won't fail.
Notice that to enable HTTPS you'll need to have a SSL cert and key, you can generate them with the following command:
openssl req -x509 -out localhost.crt -keyout localhost.key \
-newkey rsa:2048 -nodes -sha256 \
-subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
The source of that command and more information are found in this page from Let's Encrypt.
On Firefox, you can install this addon: https://addons.mozilla.org/en-US/firefox/addon/cors-everywhere/ to disable CORS for the respective tab. Then, any request will also work on file:/// URIs. Be careful though!
Either mock Ajax calls, or start web server with reverse proxy and HTTP rewriting configured, since I'm sure you don't want, or have not access to configure API server CORS headers.
If you don't want to mock ajax calls, then use either:
node-http-proxy
nginx - if you don't have nodejs and you don't want to install it.
Not Possible By Design
CORS are always blocked when attempted from a file on disk (web pages using the file:// protocol). There is nothing you can do to make it work from a file. It is simply impossible.
The reasoning for this is that files on disk have no real "origin" to allow the backend server to determine the validity of the request. You can have a file for an issue tracking html on the same disk as a file for a blog html. The server cannot know which html requested the data (you can even have someone else's file shared via Dropbox with embedded javascript that may attempt to access your server's data when you open it - nobody expects a hacking attempt when they simply open a plain html file!!).
This is why no browser vendor will allow you do make CORS requests from a file.
You Need a Server
To make it work you will need a HTTP server. There are lots of options for this from installing Apache/Nginx on your machine to running dev servers like webpack-dev-server or local-web-server. As long as the protocol is http:// or https:// you are allowed to make CORS requests.
Once you have a server serving your html file you can configure CORS on your backend as usual.
If you can not set it up access-control-allow-origin, you can try this.
Use "callback" function if your data is not in same domain.
And wrap your data "jsonCallback(" ... data ... ") as my example: http://www.ceducation.cz/akce-plnytext.json?short=1&callback=?
function jsonCallback(json) {
$.each(json, function(key, val) {
// your data is here
console.log('date: ' + val.date);
console.log('address: ' + val.address);
console.log('---');
});
}
$(document).ready(function() {
$.getJSON("http://www.ceducation.cz/akce-plnytext.json?short=1&callback=?", function(data) {
});
});
Working example

Geoserver access REST in javascript - Why 403 Forbidden? [duplicate]

I am building a web API. I found whenever I use Chrome to POST, GET to my API, there is always an OPTIONS request sent before the real request, which is quite annoying. Currently, I get the server to ignore any OPTIONS requests. Now my question is what's good to send an OPTIONS request to double the server's load? Is there any way to completely stop the browser from sending OPTIONS requests?
edit 2018-09-13: added some precisions about this pre-flight request and how to avoid it at the end of this reponse.
OPTIONS requests are what we call pre-flight requests in Cross-origin resource sharing (CORS).
They are necessary when you're making requests across different origins in specific situations.
This pre-flight request is made by some browsers as a safety measure to ensure that the request being done is trusted by the server.
Meaning the server understands that the method, origin and headers being sent on the request are safe to act upon.
Your server should not ignore but handle these requests whenever you're attempting to do cross origin requests.
A good resource can be found here http://enable-cors.org/
A way to handle these to get comfortable is to ensure that for any path with OPTIONS method the server sends a response with this header
Access-Control-Allow-Origin: *
This will tell the browser that the server is willing to answer requests from any origin.
For more information on how to add CORS support to your server see the following flowchart
http://www.html5rocks.com/static/images/cors_server_flowchart.png
edit 2018-09-13
CORS OPTIONS request is triggered only in somes cases, as explained in MDN docs:
Some requests don’t trigger a CORS preflight. Those are called “simple requests” in this article, though the Fetch spec (which defines CORS) doesn’t use that term. A request that doesn’t trigger a CORS preflight—a so-called “simple request”—is one that meets all the following conditions:
The only allowed methods are:
GET
HEAD
POST
Apart from the headers set automatically by the user agent (for example, Connection, User-Agent, or any of the other headers with names defined in the Fetch spec as a “forbidden header name”), the only headers which are allowed to be manually set are those which the Fetch spec defines as being a “CORS-safelisted request-header”, which are:
Accept
Accept-Language
Content-Language
Content-Type (but note the additional requirements below)
DPR
Downlink
Save-Data
Viewport-Width
Width
The only allowed values for the Content-Type header are:
application/x-www-form-urlencoded
multipart/form-data
text/plain
No event listeners are registered on any XMLHttpRequestUpload object used in the request; these are accessed using the XMLHttpRequest.upload property.
No ReadableStream object is used in the request.
Have gone through this issue, below is my conclusion to this issue and my solution.
According to the CORS strategy (highly recommend you read about it) You can't just force the browser to stop sending OPTIONS request if it thinks it needs to.
There are two ways you can work around it:
Make sure your request is a "simple request"
Set Access-Control-Max-Age for the OPTIONS request
Simple request
A simple cross-site request is one that meets all the following conditions:
The only allowed methods are:
GET
HEAD
POST
Apart from the headers set automatically by the user agent (e.g. Connection, User-Agent, etc.), the only headers which are allowed to be manually set are:
Accept
Accept-Language
Content-Language
Content-Type
The only allowed values for the Content-Type header are:
application/x-www-form-urlencoded
multipart/form-data
text/plain
A simple request will not cause a pre-flight OPTIONS request.
Set a cache for the OPTIONS check
You can set a Access-Control-Max-Age for the OPTIONS request, so that it will not check the permission again until it is expired.
Access-Control-Max-Age gives the value in seconds for how long the response to the preflight request can be cached for without sending another preflight request.
Limitation Noted
For Chrome, the maximum seconds for Access-Control-Max-Age is 600 which is 10 minutes, according to chrome source code
Access-Control-Max-Age only works for one resource every time, for example, GET requests with same URL path but different queries will be treated as different resources. So the request to the second resource will still trigger a preflight request.
Please refer this answer on the actual need for pre-flighted OPTIONS request: CORS - What is the motivation behind introducing preflight requests?
To disable the OPTIONS request, below conditions must be satisfied for ajax request:
Request does not set custom HTTP headers like 'application/xml' or 'application/json' etc
The request method has to be one of GET, HEAD or POST. If POST, content type should be one of application/x-www-form-urlencoded, multipart/form-data, or text/plain
Reference:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
When you have the debug console open and the Disable Cache option turned on, preflight requests will always be sent (i.e. before each and every request). if you don't disable the cache, a pre-flight request will be sent only once (per server)
Yes it's possible to avoid options request. Options request is a preflight request when you send (post) any data to another domain. It's a browser security issue. But we can use another technology: iframe transport layer. I strongly recommend you forget about any CORS configuration and use readymade solution and it will work anywhere.
Take a look here:
https://github.com/jpillora/xdomain
And working example:
http://jpillora.com/xdomain/
For a developer who understands the reason it exists but needs to access an API that doesn't handle OPTIONS calls without auth, I need a temporary answer so I can develop locally until the API owner adds proper SPA CORS support or I get a proxy API up and running.
I found you can disable CORS in Safari and Chrome on a Mac.
Disable same origin policy in Chrome
Chrome: Quit Chrome, open an terminal and paste this command: open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir
Safari: Disabling same-origin policy in Safari
If you want to disable the same-origin policy on Safari (I have 9.1.1), then you only need to enable the developer menu, and select "Disable Cross-Origin Restrictions" from the develop menu.
As mentioned in previous posts already, OPTIONS requests are there for a reason. If you have an issue with large response times from your server (e.g. overseas connection) you can also have your browser cache the preflight requests.
Have your server reply with the Access-Control-Max-Age header and for requests that go to the same endpoint the preflight request will have been cached and not occur anymore.
I have solved this problem like.
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && ENV == 'devel') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With');
header("HTTP/1.1 200 OK");
die();
}
It is only for development. With this I am waiting 9ms and 500ms and not 8s and 500ms. I can do that because production JS app will be on the same machine as production so there will be no OPTIONS but development is my local.
You can't but you could avoid CORS using JSONP.
you can also use a API Manager (like Open Sources Gravitee.io) to prevent CORS issues between frontend app and backend services by manipulating headers in preflight.
Header used in response to a preflight request to indicate which HTTP headers can be used when making the actual request :
content-type
access-control-allow-header
authorization
x-requested-with
and specify the "allow-origin" = localhost:4200 for example
After spending a whole day and a half trying to work through a similar problem I found it had to do with IIS.
My Web API project was set up as follows:
// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
//...
}
I did not have CORS specific config options in the web.config > system.webServer node like I have seen in so many posts
No CORS specific code in the global.asax or in the controller as a decorator
The problem was the app pool settings.
The managed pipeline mode was set to classic (changed it to integrated) and the Identity was set to Network Service (changed it to ApplicationPoolIdentity)
Changing those settings (and refreshing the app pool) fixed it for me.
OPTIONS request is a feature of web browsers, so it's not easy to disable it. But I found a way to redirect it away with proxy. It's useful in case that the service endpoint just cannot handle CORS/OPTIONS yet, maybe still under development, or mal-configured.
Steps:
Setup a reverse proxy for such requests with tools of choice (nginx, YARP, ...)
Create an endpoint just to handle the OPTIONS request. It might be easier to create a normal empty endpoint, and make sure it handles CORS well.
Configure two sets of rules for the proxy. One is to route all OPTIONS requests to the dummy endpoint above. Another to route all other requests to actual endpoint in question.
Update the web site to use proxy instead.
Basically this approach is to cheat browser that OPTIONS request works. Considering CORS is not to enhance security, but to relax the same-origin policy, I hope this trick could work for a while. :)
One solution I have used in the past - lets say your site is on mydomain.com, and you need to make an ajax request to foreigndomain.com
Configure an IIS rewrite from your domain to the foreign domain - e.g.
<rewrite>
<rules>
<rule name="ForeignRewrite" stopProcessing="true">
<match url="^api/v1/(.*)$" />
<action type="Rewrite" url="https://foreigndomain.com/{R:1}" />
</rule>
</rules>
</rewrite>
on your mydomain.com site - you can then make a same origin request, and there's no need for any options request :)
It can be solved in case of use of a proxy that intercept the request and write the appropriate headers.
In the particular case of Varnish these would be the rules:
if (req.http.host == "CUSTOM_URL" ) {
set resp.http.Access-Control-Allow-Origin = "*";
if (req.method == "OPTIONS") {
set resp.http.Access-Control-Max-Age = "1728000";
set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, PATCH, OPTIONS";
set resp.http.Access-Control-Allow-Headers = "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since";
set resp.http.Content-Length = "0";
set resp.http.Content-Type = "text/plain charset=UTF-8";
set resp.status = 204;
}
}
What worked for me was to import "github.com/gorilla/handlers" and then use it this way:
router := mux.NewRouter()
router.HandleFunc("/config", getConfig).Methods("GET")
router.HandleFunc("/config/emcServer", createEmcServers).Methods("POST")
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
originsOk := handlers.AllowedOrigins([]string{"*"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
log.Fatal(http.ListenAndServe(":" + webServicePort, handlers.CORS(originsOk, headersOk, methodsOk)(router)))
As soon as I executed an Ajax POST request and attaching JSON data to it, Chrome would always add the Content-Type header which was not in my previous AllowedHeaders config.

Restify and Angular CORS No 'Access-Control-Allow-Origin' header is present on the requested resource

I faced with that problem when implementing REST api with Restify secured with bearer token authorization type.
when I sending simple get request to API server it fails with CORS problem
405 (Method Not Allowed) angular.js:7962
OPTIONS http://api.host.com/tests No 'Access-Control-Allow-Origin' header is
present on the requested resource. Origin 'http://local.host.com' is
therefore not allowed access.
Solution described in my answer, so it's not real question for me, because I placed it when already know the answer, but hope it will save time for someone else in future.
The problem was faced because of restify has internal CORS module who manage CORS logic. in this module you could find list of allowed headers, by default it's
[
'accept',
'accept-version',
'content-type',
'request-id',
'origin',
'x-api-version',
'x-request-id'
]
As I say in the question, I use bearer token auth, so I send my request with Authorization header. It's not included in default list, and that's why my request fails.
To fix that problem we need to add this header to the list of ALLOW_HEADERS. for that in my restify configuration code I add this line:
restify.CORS.ALLOW_HEADERS.push('authorization');
Think that info could be helpfull if you faced with similar problem, because I spend a lot to find the solution.
You won't be able to access the URL http://api.host.com/tests from a file deployed at http://local.host.com due to the same-origin policy.
As the source (origin) page and the target URL are at different domains, your code is actually attempting to make a Cross-domain (CORS) request (thus the error with OPTIONS -- see the explanation below), not an ordinary GET.
In a few words, the same-origin policy enforces that browsers only allow Ajax calls to services in the same domain as the HTML page.
Example: A page in http://www.example.com/myPage.html can only directly request services that are in http://www.example.com, like http://www.example.com/testservice/etc. If the service is in other domain, the browser won't make the direct call (as you'd expect). Instead, it will try to make a CORS request.
To put it shortly, to perform a CORS request, your browser:
Will first send an OPTION request to the target URL
And then only if the server response to that OPTIONS contains the adequate headers (Access-Control-Allow-Origin is one of them) to allow the CORS request, the browse will perform the call (almost exactly the way it would if the HTML page was at the same domain).
If the expected headers don't come in the OPTIONS, the browser will give up, informing the error (that it attempted a CORS request and didn't find the necessary headers).
How to solve it?
Place the target service in the same domain of the origin page; or
Enable CORS (enable the necessary headers) on the server; or
If you don't have server-side access to the service, you could also mirror it (create a copy of it in the server you own).
JSONP is also a solution if you just want to request information (but this would require server-side access to setup as well).

How to tackle same origin policy in Mozilla

I am implementing YUI autocomplete in my project. I have created a web service which provides autocomplete suggestions. All things are working fine when I deploy my application and web service on same machine. But when I deploy the web service on different machine then it do not work in Firefox (But it do work in IE). I think because of same origin policy its not working in Mozilla.
Here is my autocomplete code
<script type="text/javascript">
YAHOO.example.BasicRemote = function() {
// Using an XHRDataSource to connect to web service
var oDS = new YAHOO.util.XHRDataSource("http://host_other_than_my_machine/i2b2/services/AutocompleteService/getCodes");
// Set the responseType as XML
oDS.responseType = YAHOO.util.XHRDataSource.TYPE_XML;
// Define the schema of the delimited results
oDS.responseSchema = {
resultNode: 'code',
fields: ['value']
};
// Enable caching
oDS.maxCacheEntries = 0;
// Instantiate the AutoComplete
var oAC = new YAHOO.widget.AutoComplete("myInput", "myContainer", oDS);
return {
oDS: oDS,
oAC: oAC
};
}();
</script>
My questions are
1) Is same origin policy is actual problem ? If yes then Is IE not bound to same policy as my code is working in IE ?
2) How to get rid of it ? I know some php code can be used to redirect request but how I can use it here ?
~Ajinkya.
Your problem is probably with the origin of the AJAX request, you should look into this: Cross Origin Request Security.
Basically, for apache you will need to add the following to the "host_other_than_my_machine" .htaccess file:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "http://trusted.site"
</IfModule>
Of course, replacing "http://trusted.site" with the domain you will be making the requests from.
Edit: If you need to allow access for multiple remote domains you could simply use:
Header set Access-Control-Allow-Origin "*"
This should usually not be a security concern, but be sure to thoroughly consider your specific case, ie if you are making sensitive information available through AJAX responses.
Used PHP proxy provided by Yahoo and redirected all requests to it.
http://developer.yahoo.com/javascript/howto-proxy.html

Categories