Basic Authentication with jQuery.ajax request and jsonp - javascript

I have some local html/js files with which I'd like to invoke some remote servers via https and eventually use Basic Authentication for the request.
I am encountering two problems. First is that if I don't specify 'jsonp' for the dataType, jQuery.ajax() request returns the error:
Access to restricted URI denied code:
1012
Are my requests considered cross-domain because my main work file is stored locally, but retrieving data from a server elsewhere?
So fine, I update the call so it now looks like:
$.ajax({
url: myServerUrl,
type: "GET",
dataType: "jsonp", // considered a cross domain Ajax request if not specified
username: myUsername,
password: myPassword,
success: function(result)
{
// success handling
},
error: function(req, status, errThrown){
// error handling
}
})
Because I need to use Basic Authentication, I'm passing in the username/password but if I monitor the request, I don't see it being set and additionally, the server sends an error response since it doesn't have the expected info.
Additionally, because I have jsonp set, beforeSend won't get invoked.
How do I pass along the credentials using Basic Authentication for this request?

The short version is you can't do this. Your suspicions are correct, because you're local and these files are remote, you can't access them, you're being blocked by the same-origin policy. The work-around for that is JSONP, but that really doesn't seem to apply to your situation...
JSONP works differently, it's a GET request via a <script> tag include to get the file, so you're not sending special headers or anything.
You'll need to proxy the request through the server you're on (the domain of where this script is running) or another proxy option, but going from the client to another domain is blocked, mainly for security reasons.

Try doing http://user:password#restservice. This mimics a basic-auth request.

I think you'll have to add a server proxy of some sort. JSONP is just a particular way to use a script tag. Thus, it doesn't allow setting arbitrary headers. And of course, you can't do a cross-origin XHR.

Related

Cross domain AJAX called with JSONP returns plain JSON

I have encountered a problem with an API I want to use. The API returns plain JSON but its a cross domain AJAX call so I have to use jsonp.
$.ajax({
type: "GET",
url: url + query,
contentType: "application/json",
dataType: "jsonp",
success: function(data){
console.log(data);
}
});
The problem is when I change the dataType to "json" an error occurs:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'X' is therefore not allowed access.
This is because its a cross domain ajax call. But when it is jsonp it says:
Uncaught SyntaxError: Unexpected token :
In other words it does not recognize the json format.
I am using jquery for the ajax call. Any suggestions how to solve this?
Since you dont have access to the server where the API is hosted, you use can a web service utility like CURL to access the API. AJAX calls requires CORS (Cross Origin Resource Sharing) to be enabled on the server where the API is served.
You can call a web service on your local server page via AJAX from where the CURL call will be made and appropriate response returned.
There are several methods of bypassing cross-domain restrictions (CORS, JSONP, Iframe transport, etc.) but all methods have in common that the API server needs to corporate. So if you don’t have privileges on the API server, you cannot come across the cross-domain restrictions.
The only way to make this work would be putting a proxy in front of the API that you can control (the proxy could either live on the same domain or inject the appropriate CORS headers). However, this will affect performance and might also have legal implications.
Regarding JSONP, here’s an excellent explanation of how and why this works:
What is JSONP all about?

REST request from app works, but not from javascript

I'm building an app that has to get and set data at a remote web service through requests. When I use the jQuery GET request it works fine, I can request data from the service without any problems, but when I use PUT I get some erros:
OPTIONS http://myurl.com 501 (Unsupported method
('OPTIONS'))
OPTIONS http://myurl.com Origin null is not allowed by Access-Control-Allow-Origin.
I've tried almost anything to get this to work, but it won't work. I've download a chrome app called REST Console, which can make custom REST requests. The strange thing is that I can interact with my server over that app but not through my javascript!
This is the javascript:
$.ajax({
url: 'http://myurl.com',
type: 'PUT',
data: '<time>16:00</time>',
success: function(data) { alert(data); }
});
Could anybody tell me what is going on here?
First ensure you're serving the page that runs the script from a web server, not directly from the file system.
I'm guessing your service at http://myurl.com is at a different host name to the host name your page is being served from? For it to work in this case you need to implement HTTP headers to support Cross Origin Resource Sharing.
Your service at http://myurl.com needs to handle an HTTP OPTIONS request, the response to which should be a set of HTTP headers (with no content) as follows:
Access-Control-Allow-Origin: http://url-of-page-with-javascript/
Optionally you can also specify Access-Control-Allow-Credentials, Access-Control-Allow-Headers and Access-Control-Allow-Methods. See the full specification here.
You'll also need to add the same headers with the same values when your server responds to the PUT request - obviously the content will also be included with this response.

Connect to webService using AJAX and CORS

I'm developing a phonegap App with html5, css, js and jQuery Mobile and I need to connect to a webservice which is already done and fully working. The problem is the Access Control Allow Origin and the Cross Domain. As if it wasn't hard enough I have to think about the authentication too, essential to connect to the web service. I already done my research, read a lot of tuts, tried a lot of solutions, some of them using jsonP which looked to me the closest one to work. The thing is I'm new at this and no tutorial looked good, so hopefully someone here could lead me the way. The webService was build in asp.net and I have full access to it if it's needed. I'm using AJAX to make the "call" but I can't pass the ForeFront authentication .
Here's the JS+AJAX code:
function conteudoProg() {
var webMethod = "myURL";
var credentials = {
username : "myUser",
password : "myPass"
};
$.ajax({
type : "GET",
url : webMethod,
//data: credentials,
contentType : "application/json; charset=utf-8",
dataType : "jsonp",
success : function(msg) {
alert(msg);
},
error : function(e) {
alert(e.status + " " + e.statusText );
}
});
}
If I change my dataType from jsonp to json, I get this error:
OPTIONS https://myURL 440 (Login Timeout)
XMLHttpRequest cannot load https://myURL Origin http://127.0.0.1:8020 is not allowed by Access-Control-Allow-Origin.
With jsonp, the error looks like this:
Resource interpreted as Script but transferred with MIME type text/html: "https://myURL/CookieAuth.dll?GetLogon?curl=Z2FWSInqueritosZ2FServ…1820135927463_1359737732559Z26_Z3D1359737732605&reason=0&formdir=3". jquery-1.8.2.min.js:2
Uncaught SyntaxError: Unexpected token <
Requests to another domain will cause a pre-flight OPTIONS request to see whether the requesting domain can make calls to this domain.
The receiving end needs to emit the correct headers or your browser will block the request and give you the error you posted.
Say you are requesting from mydomain.com to webservice.com
Then webservice.com/api should emit these headers:
Access-Control-Allow-Origin: http[s]://mydomain.com
Access-Control-Allow-Credentials: true # if you want cookies
Access-Control-Allow-Headers: Content-Type, X-Custom-Header # any extra headers you want to send
Make sure the webservice knows about OPTIONS requests. It really only needs to emit some CORS headers, it doesn't need to do anything else (like process a request to it's API).
You don't need to change anything in your AJAX handler, it will pass as any other request. If you want cookies make sure to set http_request.withCredentials = true;
Keep in mind that an HTTPS URL is considered to be different from an HTTP domain and make sure your HTTPS certificate is valid, if it's not valid the request may fail silently. If you're using a self-signed certificate (for testing) add it to your browser or OS whitelist.
Cross domain request from HTTP to HTTPS aborts immediately
As for compatibility. Earlier versions of Internet Explorer (8 and lower) use ActiveXObject, this API is very bad at CORS. It doesn't support authentication/cookies or custom headers (such as Content-Type: application/JSON). I would recommend a JSONp fallback.
The code does not work because when you tell jQuery that the .ajax method expects a dataType json, that's what's trying to parse the response into. If the response is html then you should use a dataType html (or none, to let the default intelligent guess do it's work). See jQuery.ajax() dataType for more info.

jQuery cross domain image upload

Ok, so basically.
I inject some javascript code into a web page and it uploads an image on that page to another server.
Now I have it working when I run it on my domain (of course), but I need to post the multipart/form-data request to a PHP file that I do not own.
Since it is a upload and not a simple request to just get data, I cannot use jsonp in the initial call since the response would not be in json.
Using James Padolsey's cross domain script, I am able to do $.get and $.post request across domains, but since I am using $.ajax it does not work.
He uses the Yahoo Query Language to acomplish this
This is basically how I am making the request
$.ajax({
url: 'http://website.com/upload.php',
type: 'POST',
contentType:'multipart/form-data',
data: postData,
success: successCallback,
error : function(XMLHttpRequest, textStatus, errorThrown) {
console.log('Error');
}
});
I want to make it completely JavaScript based to avoid making my server do the request.
So to re-cap, I can get the image bytes and make the request with javascript. But so far I cannot make it cross domain since I am $.ajax to set the content Type to "multipart/form-data".
Is there another way to make the request cross domain with or without the YQL?
Making the request with an iframe will not work since the domain of the iframe would change and I would not have access to the response.
This is a well known and difficult problem for web development, know as the Same Origin Policy
Javascript prevents access to most methods and properties to pages across different origins. The term "origin" is defined using the domain name, application layer protocol, and (in most browsers) port number of the HTML document running the script. Two resources are considered to be of the same origin if and only if all these values are exactly the same.
There are several ways around this.
Create your own proxy
Create a page that simply forwards the request to the other server, and returns its response
or, Use Apache's rules to form a proxy (see above link)
Use someone else's proxy
For GET requests which are typical Use YQL to access yahoo's proxy
For POST requests, if the 3rd party supports Open Data Tables
or, Use some other public proxy
See if the 3rd party conforms to the CORS specification
Cross domain POST query using Cross-Origin Resource Sharing getting no data back
If you are willing to allow a little flash on your page, try flXHR
it claims to implement the exact XHR api and also has a jquery plugin
These are pretty much your only options

Sending POST message with AJAX Problem

I am currently trying to send a POST message which works fine except for the error that there are not correct credentials. However, after I add the credentials header, the message type is changed into OPTIONS and fails. I do not understand how adding a header causes the type to change to OPTIONS. Any help would be appreciated.
ajaxRequest = $j.ajax({
url: url,
type: 'POST',
beforeSend : function(req) {
req.setRequestHeader('Authorization', auth),
}
success: function(data, status) {
console.log("Success!!");
console.log(data);
console.log(status);
},
error: function(xhr, desc, err) {
console.log(xhr);
alert('fail')
console.log("Desc: " + desc + "\nErr:" + err);
}
});
EDIT: just to be more clear, I can literally go in and comment out the setRequestHeader function and it sends the message POST.
The problem you're encountering is because of cross-domain restrictions when using AJAX. When you try to set an authorization header, the browser issues what's known as a pre-flight request to see if the server will accept requests from this domain.
A pre-flight request is typically sent as an OPTIONS request. If the server you're invoking doesn't return an Access-Control-Allow-Origin header that matches your domain, the AJAX request is blocked.
There's more on this here: Cross-Origin Resource Sharing
"User agents can discover via a preflight request whether a cross-origin resource is prepared to accept requests, using a non-simple method, from a given origin."
I've run into the same problem- there are a few possible workarounds depending on your scenario.
If you have any way of setting the above mentioned header on the 3rd party server (some applications/services offer this) then that's probably the easiest way.
There's also a javascript library called EasyXDM that may work for you, but again, it will only be of use if you have access to the 3rd party server to upload a configuration file for this library.
Other options to investigate are PostMessage and Cross Domain Iframe communication. The latter is more of an old-school hack, the former is the recommended approach for newer browsers. It won't work for IE6/7.
The option we will probably end up using is a simple proxy- invoke our own server with the AJAX request, and on the server invoke the 3rd party server. This avoids the cross domain issue entirely, and has other advantages for our scenario.
I guess this is a problem in Internet Explorer. without explicitly telling the request-method (POST|GET) the request header doesn't contain the custom-header in IE, but it works in other browsers.
Yet try to post this in the bugs for jquery. Also try in other browsers.
Edit 1 : I saw this as a bug in jQuery 1.4.x .... I reported a bug report now.
The OPTIONS response happens when the server does not know how to respond to the ajax request.
I've seen it happen often when trying to post to a third-party domain (i.e. cross-site posting)
The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI. This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.
Have you tried:
Having some sort of callback on the url that is being posted to?
Explicitly setting the headers (I'm assuming you're using PHP) on the url that is being posted to?

Categories

Resources