I am trying to make a cross-site request, on a site that needs authentication. The authentication works with a cookie.
For some reason, when I am doing this call :
$.getJSON(url + '?', function(data){
alert(data);
});
I don't see the Cookie sent in the HTTP headers. While when I just copy paste url in my address bar, the call is successful, and Cookie is set properly...
I tried to replace the $.getJSON by a $.ajax, and set manually the request headers. It resulted in the request not even visible in firebug (while I know it has been sent and answered to by using another tool)!!!
I am using firefox 3.6, jquery 1.4
Any idea on what's going on ?
This is part of the same origin policy, JSONP requests to other domains will not have any cookies sent with them.
Related
I am working on twitter login using Jquery and Plain Java Script.
I have completed most of work, I am trying to get request_token from https://api.twitter.com/oauth/request_token URL. Request goes from my page as well but everytime it send me error of:
jquery.js:9536 OPTIONS https://api.twitter.com/oauth/request_token 400 ()send # jquery.js:9536ajax # jquery.js:9143clickToCalculate # twt.html:71onclick # twt.html:423
twt.html:1
XMLHttpRequest cannot load
https://api.twitter.com/oauth/request_token. Response for preflight has invalid HTTP status code 400
twt.html:82
Object {readyState: 0, status: 0, statusText: "error"}
My request URL page is http://kurbhatt.github.io/twt.html, you can check it's page source as well from https://github.com/kurbhatt/kurbhatt.github.io/blob/master/twt.html source page.
I have put valid and enough data from twitter apps to this page.
Can anyone tell me why I am facing this issue ?
Since last 3-4 days I am working on this issue, still not get solution for the issue.
And sometimes it gave me another type of error:
XMLHttpRequest cannot load https://api.twitter.com/oauth/request_token. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://kurbhatt.github.io' is therefore not allowed access. The response had HTTP status code 400.
You are making a "GET" request to the api.
twitter api for request_token accepts only POST.
Fix your ajax request to make a POST request. The option is method not type
$.ajax({
method: "POST",
...
well, i would like to reply your comment in the comment, but that would be too tiring.
what you need to do to get the request token is do an HTTP POST to api.twitter.com/oauth/request_token with addtional headers, that is Authorization header, as stated in this twitter docs.
you can easily do that by creating a cURL POST request from your web server to the url above, let's say you have that cURL page in yourdomain.com/twittercurl, therefore you can make your jQuery call to that page instead of the twitter request token URL.
as I don't know which server side programming language you are using, you need to find the appropriate cURL call.
but, aside from that, here are some links to read, maybe you can find usefull informations from it:
adding request header to jQuery ajax call
cross domain ajax call
and don't forget the twitter docs mentioned above
lastly, you can also read this PHP library for the server side cURL request
I know this has been asked before in various forms, but I can't seem to get around the problem.
I have tried using both jQuery and the native JS API to make the Ajax requests.
My situation is the following (see attached diagram):
Browser makes HTTP request
Server responds and sets persistent Cookie
Browser makes HTTP Ajax request, Cookie is there alright
Server responds as expected, updates Cookie
Browser makes HTTPS Ajax request, Cookie is not there anymore (?!)
Server gives "default" response, since there is no Cookie (unintended behaviour)
Before anybody starts a lecture on cross-domain requests let me state a couple of things:
I know that this is a cross-domain request (different protocol), and that's why the Server sets the Access-Control-Allow-Origin header in the response (and I am using Chrome and Firefox, both of which support CORS)
What I also know, though, is that the HTTP cookie ought to be manageable over HTTPS (see here) since the host is the same
(EDIT) The cookie is properly set for the general domain (e.g. .domain.ext) and neither the HttpOnly nor the Secure flags are set
So, why, why, why doesn't the browser pass on the cookie when making the HTTPS Ajax call? Any ideas? I am about to lose my mind...
+-----------+ HTTP Request +-----------+
|Browser |+---------------->|Server |
+-----------+ +-----------+
HTTP Response
<----------------+
Set-cookie
Ajax HTTP Req.
+---------------->
Cookie (OK)
HTTP Response
<----------------+
Set-cookie (OK)
Ajax HTTPS Req.
+---------------->
No Cookie (!!!)
Ok, found the solution to the cookie problem.
See XHR specs, jQuery docs and StackOverflow.
The solution to have the cookies sent when switching protocol and/or subdomain is to set the withCredentials property to true.
E.g. (using jQuery)
$.ajax( {
/* Setup the call */
xhrFields: {
withCredentials: true
}
});
Document.cookie and Ajax Request does not share the cookie. Otherwise, ajax can't access the cookies from document.cookie or the response headers. They can only be controlled by the remote domain.
If you first get response including cookie from server by ajax, Since that you can request ajax communication with cookie to server.
For this case, you write such as below code (jQuery)
$.ajax({
xhrFields : {
withCredentials : true
}
});
See this article and demo
I attempt to send a GET request in a jQuery AJAX request.
$.ajax({
type: 'GET',
url: /* <the link as string> */,
dataType: 'text/html',
success: function() { alert("Success"); },
error: function() { alert("Error"); },
});
However, whatever I've tried, I got XMLHttpRequest cannot load <page>. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:7776' is therefore not allowed access.
I tried everything, from adding header : {} definitions to the AJAX request to setting dataType to JSONP, or even text/plain, using simple AJAX instead of jQuery, even downloading a plugin that enables CORS - but nothing could help.
And the same happens if I attempt to reach any other sites.
Any ideas for a proper and simple solution? Is there any at all?
This is by design. You can't make an arbitrary HTTP request to another server using XMLHttpRequest unless that server allows it by putting out an Access-Control-Allow-Origin header for the requesting host.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
You could retrieve it in a script tag (there isn't the same restriction on scripts and images and stylesheets), but unless the content returned is a script, it won't do you much good.
Here's a tutorial on CORS:
http://www.bennadel.com/blog/2327-cross-origin-resource-sharing-cors-ajax-requests-between-jquery-and-node-js.htm
This is all done to protect the end user. Assuming that an image is actually an image, a stylesheet is just a stylesheet and a script is just a script, requesting those resources from another server can't really do any harm.
But in general, cross-origin requests can do really bad things. Say that you, Zoltan, are using coolsharks.com. Say also that you are logged into mybank.com and there is a cookie for mybank.com in your browser. Now, suppose that coolsharks.com sends an AJAX request to mybank.com, asking to transfer all your money into another account. Because you have a mybank.com cookie stored, they successfully complete the request. And all of this happens without your knowledge, because no page reload occurred. This is the danger of allowing general cross-site AJAX requests.
If you want to perform cross-site requests, you have two options:
Get the server you are making the request to to either
a. Admit you by putting out a Access-Control-Allow-Origin header that includes you (or *)
b. Provide you with a JSONP API.
or
Write your own browser that doesn't follow the standards and has no restrictions.
In (1), you must have the cooperation of the server you are making requests to, and in (2), you must have control over the end user's browser. If you can't fulfill (1) or (2), you're pretty much out of luck.
However, there is a third option (pointed out by charlietfl). You can make the request from a server that you do control and then pass the result back to your page. E.g.
<script>
$.ajax({
type: 'GET',
url: '/proxyAjax.php?url=http%3A%2F%2Fstackoverflow.com%2F10m',
dataType: 'text/html',
success: function() { alert("Success"); },
error: function() { alert("Error"); }
});
</script>
And then on your server, at its most simple:
<?php
// proxyAjax.php
// ... validation of params
// and checking of url against whitelist would happen here ...
// assume that $url now contains "http://stackoverflow.com/10m"
echo file_get_contents($url);
Of course, this method may run into other issues:
Does the site you are a proxy for require the correct referrer or a certain IP address?
Do cookies need to be passed through to the target server?
Does your whitelist sufficiently protect you from making arbitrary requests?
Which headers (e.g. modify time, etc) will you be passing back to the browser as your server received them and which ones will you omit or change?
Will your server be implicated as having made a request that was unlawful (since you are acting as a proxy)?
I'm sure there are others. But if none of those issues prevent it, this third method could work quite well.
you can ask the developers of that domain if they would set the appropriate header for you, this restriction is only for javascript, basically you can request the ressource from your server with php or whatever and the javascript requests the data from your domain then
Old question, but I'm not seeing this solution, which worked for me, anywhere. So hoping this can be helpful for someone.
First, remember that it makes no sense to try modifying the headers of the request to get around a cross-origin resource request. If that were all it took, it would be easy for malicious users to then circumvent this security measure.
Cross-origin requests in this context are only possible if the partner site's server allows it through their response headers.
I got this to work in Django without any CORS middleware by setting the following headers on the response:
response["Access-Control-Allow-Origin"] = "requesting_site.com"
response["Access-Control-Allow-Methods"] = "GET"
response["Access-Control-Allow-Headers"] = "requesting_site.com"
Most answers on here seem to mention the first one, but not the second two. I've just confirmed they are all required. You'll want to modify as needed for your framework or request method (GET, POST, OPTION).
p.s. You can try "*" instead of "requesting_site.com" for initial development just to get it working, but it would be a security hole to allow every site access. Once working, you can restrict it for your requesting site only to make sure you don't have any formatting typos.
I am going crazy with cookies and ajax call.
My configuration is simple. I run a website on 8282 port, (localhost.com:8282). My website calls some webservices on 8080 port (localhost.com:8080). Of course I add a line in my hosts file to avoid localhost trouble :
127.0.0.1 localhost.com
I try to set a cookie when the webservice is called with ajax. Here is my response header that I can see with Chrome debugger :
Set-Cookie:token=Custom eyJ0aW1lc3RhbXAiOiIxNDI0NzE5Mzc5ODY3IiwgImlkIjoiNTRlNzZkZGU2ZDk3ZGM1MjYxZjQzMzFlIiwgInNpZ25hdHVyZSI6Im5tZnFGeEEvYlc0TFJGNFJNb3dBZXJZOUw0aWw0aEorcFh1YUt5b3VFK0k9In0=;domain=.localhost.com;path=/;
The cookie is never stored by Chrome. However, when I use Rest client extension and I call the same webservice, the cookie is stored by Chrome ! So my cookie is well formed but is not stored with ajax call.
It's likely an issue with CORS (Cross Origin Resource Sharing, i.e the fact that the domain of the client and of the target of the AJAX call are not the same). For cookies to work well in a CORS configuration, you need to set the withCredentials flag to true. How to do so varies depending on you AJAX library (if you're using one).
See here: http://www.html5rocks.com/en/tutorials/cors/
In your close reponse of ajax you can set your cookie
document.cookie = "token=Custom eyJ0aW1lc3RhbXAiOiIxNDI0NzE5Mzc5ODY3IiwgImlkIjoiNTRlNzZkZGU2ZDk3ZGM1MjYxZjQzMzFlIiwgInNpZ25hdHVyZSI6Im5tZnFGeEEvYlc0TFJGNFJNb3dBZXJZOUw0aWw0aEorcFh1YUt5b3VFK0k9In0=;domain=.localhost.com;path=/";
Can an AJAX response set a cookie?
I swear I saw an article about this at one point but can not find it...
How can I perform a jQuery ajax request of type POST on another domain? Must be accomplished without a proxy. Is this possible?
Yes you can POST all you want, even $.post() works...but you won't get a response back.
This works, the other domain will get the POST:
$.post("http://othersite.com/somePage.php", { thing: "value" }, function(data) {
//data will always be null
});
But the response, data in the above example, will be null due to the same-origin policy.
All the options I've experimented with:
1) PORK: http://www.schizofreend.nl/Pork.Iframe/Examples/ Creates an iframe and submits the post there, then reads the response. Still requires same base domain per
request (i.e. www.foo.com can request
data from www2.foo.com, but not from
www.google.com) . Also requires you to
fiddle with the document.domain
property, which causes adverse side
effects. And there's a pervasive problem in all the major browsers where reloading the page basically shuffles the cached contents of all iframes on the page if any of them are dynamically written. Your response data will show up in the box where an ad is supposed to be.
2) flxhr: http://flxhr.flensed.com/ Can even be used to mask jQuery's built-in ajax so you don't even notice it. Requires flash though, so iPhone is out
3) jsonp: Doesn't work if you're posting a lot of data. boo.
4) chunked jsonp: When your jsonp request is too big, break the query string up into manageable chunks and send multiple get requests. Reconstruct them on the server. This is helpful but breaks down if you're load balancing users between servers.
5) CORS: http://www.w3.org/TR/cors/ doesn't work in older browsers (IE7, IE6, Firefox 2, etc)
So we currently do the following algorithm:
If request is small enough, use JSONP
If not small enough, but user has flash, use FlXHR
Else use chunked JSONP
Spend one afternoon writing that up and you'll be able to use it for good. Adding CORS to our algorithm might be good for faster iPhone support.
If you have control over the code running at the other domain, just let it return an appropriate Access-Control-Allow-Origin header in the response. See also HTTP Access-Control at MDC.
If you want a fire and forget POST where you don't care about the response then just submit a form to a hidden iframe. This requires a Transitional Doctype.
<form method="POST" action="http://example.com/" target="name_of_iframe">
If you want to parse the response, then using a proxy if the only real option.
If you are desperate, and control the remote site, then you can:
Submit a form as above
Set a cookie in the response (which might be blocked before the iframe could cause the cookie to be considered '3rd party' (i.e. likely to be advertising tracking).
Wait long enough for the response to come back
Dynamically generate a script element with the src pointing to the remote site
Use JSON-P in the response and take advantage of the data previously stored in the cookie
This approach is subject to race conditions and generally ugly. Proxing the data through the current domain is a much better approach.
If you need to know that the POST was successful, and don't have control over the remote server:
$.ajax({
type:"POST",
url:"http://www.somesite.com/submit",
data:'firstname=test&lastname=person&email=test#test.com',
complete: function(response){
if(response.status == 0 && response.statusText == "success")
{
/* CORS POST was successful */
}
else
{
/* Show error message */
}
}
});
If there was a problem with the submission then response.statusText should equal "error".
Note: some remote servers will send the HTTP header Access-Control-Allow-Origin: *, which will result in a 200 OK HTTP status code response. In that case, ajax will execute the success handler, and this method is not needed. To look at the response just do console.log(JSON.stringify(response)); or use FireBug's 'Net' panel.