CrossDomain issue when making Ajax call to Web API - ajax

I have several projects in my solution: WebApi and WebPage project
Web API project returns me some data using the following Url:
http://localhost:63983/api/values
My main web project it uses another Port:
http://localhost:63421/#/
And now when I run my Web Project, I'm trying to make a simple Ajax call to my WebApi
And here I get a very strange error:
Firebug shows status: 200OK, but it marks it with a red color and I get no data.
I presume it has something to do with cross-domains maybe.

You guess is exactly right. You are not allowed to read data on a different domain. A domain is both the domain name and the port. This also applies when one is on HTTP (port 80), and the other is on HTTPS (port 443)
You can explicitly allow you WebProject to make AJAX calls to your WebApi by setting a header value in the content returned by your WebApi. So when you make an AJAX call to http//localhost:63983/api/values, it should include the HTTP header:
Access-Control-Allow-Origin: http://localhost:63421
More details can be found here: http://css.dzone.com/articles/ajax-requests-other-domains

You can enable CORS support in Web API using the Microsoft.AspNet.WebApi.Cors nuget package.
After installing the above package, having the following configuration should fix your issue.
config.EnableCors(new EnableCorsAttribute(origins: "*", headers: "*", methods: "*"));
More info here:
http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Related

Is it possible to proxy the html get request to /graphql from a create-react-app?

I have a create-react-app application in which I enabled the proxy by adding:
"proxy": "http://localhost:3001",
to my package.json. That's working well for API requests to /graphql, but when the web browser request /graphql (for the purpose of loading the UI to run queries) gets handled by the frontend and not proxied. Is it possible to also proxy it?
Same thing happens when I try to do OAuth by visiting https://localhost:3000/auth/facebook, the frontend handles it instead of the backend.
It is indeed possible to further customize the proxy.
First, when a web browser requests /graphql or /auth/facebook, it sends an Accept header that holds text/html (among others). The configuration of the CRA proxy specifically ignores requests with this header value:
The development server will only attempt to send requests without text/html in its Accept header to the proxy.
(emphasis in original text)
Luckily, you may override the default configuration and basically hook the proxy middleware to your liking. There are detailed instructions in the docs and even more so in the npm package docs, but the crux of it is:
app.use(
'/graphql',
createProxyMiddleware({
target: 'http://localhost:3001',
changeOrigin: true,
})
);

Angular + Django: Sending POST request with cookies (CORS)

I'm developing an app using Angular for client side and Django for server side. During development I'm running Django in port 8000 for managing all API requests, and serving my client app using Angular CLI running at port 4200.
Sending GET requests to Django work w/o problems but when I try to send a POST request that includes some cookies with session information, it fails as the cookies are not included in the header.
I know that the source of this "problem" is the CORS issue [read more here] and that it won't be a problem in production as both client and server apps will be running in the same server and port, however I wonder how can I fix this situation at least for development.
I've tried using the django-cors-headers module with the options CORS_ALLOW_CREDENTIALSand CORS_ORIGIN_ALLOW_ALL set to True but it didn't work.
Any ideas?
Finally I managed to make all work.
I thought it was a problem of Django so I installed django-cors-headers module, however the "problem" is in the browser (actually is not a problem, it is a security issue, see [here][1]).
Anyway, I solved the problem using a proxy rule for my Angular CLI, as follows:
First, instead of sending my requests to http://localhost:8000/api/..., I send them to /api/ (i.e. to my Angular server running at port 4200).
Then I added a file in my Angular project called "proxy.conf.json" with the following content:
{
"/api": {
"target": "http://localhost:8000",
"secure": false
}
}
Finally, I added the flag "--proxy-config" to the Angular CLI server:
ng serve --watch **--proxy-config proxy.conf.json**
Now, all API requests are sent to the port 4200 and Angular internally redirects them to Django, avoiding the CORS problem.
Note: With this solution I didn't need anymore the django-cors-headers module.

Access-Control-Allow-Origin issue in XMLRPC request

Am working in Mobile App develoment using HTML5 + Phonegap. Currently am working a mobile App using XMLRPC and its working fine. (Android and iOS)
I need to work the same application as a website in browsers. (using HTML5).
But when am trying to Run my application on website i am getting this error :
XMLHttpRequest cannot load 'Client' URL'. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost <http://localhost/>' is therefore not allowed access.
When am search experts says that use JSONP. But using same XMLRPC method can i work it ?
For example ;
For a Login purposes am using ;
$.xmlrpc({
url: 'http://clienturl/xmlrpc/common',
methodName: 'login',
params: [Database_name','user_name','Password'],
success: function(response, status, jqXHR) {
alert('success'); },
error: OnError
});
Its working fine as a Mobile Application.
But gets Access-Control-Allow-Origin cross domain issue when i am trying to run as a Website.
How can i fix this ?
By default the SOP (same origin policy) allows cross-origin requests, but it prevents receiving the responses of those requests. The Access-Control-Allow-Origin in your error message is a CORS (cross-origin resource sharing) header. It tells the browser that you allow reading the responses of a domain (your XMLRPC server's domain) by sending requests from another domain (your XMLRPC client's domain). So you have to send back CORS allow headers from your server if you want to call it with AJAX.
note: CORS won't work in old browsers.
Possible solutions:
If you call http://clienturl/xmlrpc/common from http://localhost then the
response.header('Access-Control-Allow-Origin', "*")
is one not so secure solution according to this: Origin http://localhost is not allowed by Access-Control-Allow-Origin
But you can always add another hostname (e.g. http://client.xml.rpc) for your client, for example by windows you can modify the hosts file and add a binding using the IIS server.
I don't recommend this solution, because it is a security risk with the allow credentials header.
Another more secure options is to make a list of allowed hosts, check from which host you got the actual request, and send back the proper header:
if (allowedHosts.contains(request.host))
if (request.host== "http://localhost")
response.header('Access-Control-Allow-Origin', "null");
else
response.header('Access-Control-Allow-Origin', request.host);
else
response.header('Access-Control-Allow-Origin', server.host);
This is the proper solution with multiple hosts, because if you allow credentials for *, then everybody will be able to read and write the session of a logged in user.
By http://localhost and file:/// IRIs you have to use the null origin. I am unsure about other protocols, I guess in the current browsers you have to use null origin by them as well.

URL not allowed by Access-Control-Allow-Origin

I am trying to implement OAUTH for accessing Flickr APIs. My AJAX call to flickr.com keeps failing.
Sample Error Message:
XMLHttpRequest cannot load http://www.flickr.com/services/oauth /request_token?oauth_callback=oob&oauth…signature_method=HMAC-SHA1&oauth_timestamp=1368375405647&oauth_version=1.0. Origin http://localhost:8080 is not allowed by Access-Control-Allow-Origin.
Initially I used chrome and read the html file as file://path. I used to get the error 'null not allowed by access-control-allow-origin'. I solved this problem by copying the html file to 'local IIS server', 'local python webserver' and then a 'remote webserver'. I created python web server using > python -m http.server 8080'
I realize my cross browser call to flickr.com using XMLHttpRequest is failing. I tried by various solutions suggested in this forum:
Using newer Chrome 26.0.1410.64 m, which I guess supports CORS
I launched chrome with --disable-web-security
I created a web server using python -m http.server 8080 on local machine and then on a remote machine and copied the html file to the site
I copied file to a local MSFT IIS server
I defined URL in etc/hosts file to avoid numeric IP
I still get the same error (with relevant URL in the error message)
code clipping:
urlString="http://www.flickr.com/services/oauth/request_token?"+
"oauth_callback="+"oob"+'&'+
"oauth_consumer_key="+consumerKey+'&'+
"oauth_nonce="+nonce+'&'+
"oauth_signature="+esignature+'&'+
"oauth_signature_method="+macAlgorithm+'&'+
"oauth_timestamp="+timeStamp+'&'+
"oauth_version=1.0";
$.ajax({
url: urlString,
success:function(data){
alert(data);
}
});
In order to CORS work, both ends must enable it.
The first end is the browser, and, as you are using Chrome 26.*, yours is ok.
The second end is the server:
Before making a GET request to a domain different than the one the page is on, the browser sends an OPTIONS request to that domain. In response to this request, the server should include some headers that tell if a cross-domain request (GET, POST or other) is allowed.
One of those headers is Access-Control-Allow-Origin.
So when you run your page from your file system (file:// "protocol"), the OPTIONS means something like "Flickr, can I make a cross-domain call to you? I'm calling from null". Flickr does not recognize that domain as allowed and returns the error you are getting.
Same way, when you run your page from your local server, the OPTIONS says "(...) I'm calling from localhost:8080". Flickr does not recognize that domain as allowed as well.
The solution:
I don't know the Flickr oauth service, but I know that, as any other service, to make a CORS call to it, the page must be in a domain allowed by it. From your tests, I'm guessing Flickr does't allow many other domains.
But... an alternative to CORS is JSONP. I did a little research, Flickr oauth seems to support it.
Check this page for details: http://www.flickr.com/services/api/explore/flickr.auth.oauth.getAccessToken
There's another question talking about that specific subject:
Is JSONP supported in the new Flickr OAuth API?
About JSONP, this can get you started: How to make a JSONP request from Javascript without JQuery?
It is not possible to implement Oauth 1.0 through just javascript without any server side script. Since the flickr's new authentication process is based on Oauth 1.0a. You got to use a server-side script.
I tried to send the token request using JSONP in FireFox with CORS on(using a third-party add-on) and it worked fine. But without using any add-ons, it's not possible as the response from flickr is in text format(not in a JSON format) and the request fails.
You can either use server-side code for token request. OR Use the deprecated flickr API for authentication.

ColdFusion not handles HTTP OPTIONS requests for CFC

Scenario:
A webserver which hosts a frontend application based on ExtJS.
A ColdFusion 10 server (with Apache) that hosts backend services.
Frontend application make AJAX requests to ColdFusion components (CFC) with form http://<CF_server>/<app_path>/<CFC>?method=someMethod&...
CFC responds with JSON.
Since frontend and backend are on different servers we are in a CORS (Cross-Origin Resource Sharing) environment and AJAX requests making two http requests to backend: first is an OPTIONS method for handshake and second is a POST request. I have need enabling headers in Apache on CF server and using "Header set Access-Control-Allow-Origin: *" directive for enabling CORS, but I would like handling headers programmatically from CF not Apache. I have run some test and I noticed that OPTIONS method in http request works only with CFM and not with CFC, so the first AJAX request (with OPTIONS method) fails. I can bypass OPTIONS request in AJAX call setting useDefaultXhrHeader properties, but I would understand CF behavior.
After running tests with cfhttp tag I have found that:
HTTP request with OPTIONS method to CFM are similar to GET method: triggers events method on Application.cfc (orRequestStart, ...), returns filecontent and headers.
HTTP request with OPTIONS method to CFC don't triggers events, don't return filecontent nor headers.
A call (with OPTSIONS method) to unexistants CFC return same result.
Why CF not handle OPTIONS method when calling CFC?
In my tests i have bypassed Apache using integrated CF webserver on port 8500. I have also tried on CF9 with same results. Railo, instead, has a different behavior: handles OPTIONS method also for CFC.
This is similar as this thread without response: http://www.houseoffusion.com/groups/cf-talk/thread.cfm/threadid:59715
Thanks.
I've run into the same kind of issue with both CF and Apache CXF recently.
It seems CF has no defined behavior for verbs other that GET and POST. In my case, I installed the CORS filter here: http://software.dzhuvinov.com/cors-filter-installation.html
That intercepts the requests and handles them before they make it as far as your app. It worked for CXF and should work for CF, but the downside is that it requires a change to your web.xml, which may not be allowed in certain hosting setups.
The other option is to configure apache to add the necessary headers: http://enable-cors.org/server_apache.html
I also found a number of differences between browser vendors in when they use an OPTIONS call. I can't remember the specifics, but test early cross-browser if that's an eventual requirement.

Resources