Onedrive cors download in javascript - javascript

I'm trying to process onedrive files in client-side javascript, but first I need a way to use XMLHttpRequest to download the file. Onedrive supports cors for a lot of operations, but for downloading the file into javascript there is the following problem:
As mentioned here: onedrive rest api manual
I can send a request to:
GET https://apis.live.net/v5.0/FILE_ID/content?access_token=ACCESS_TOKEN
and it will reply with a location header redirecting the browser to the file. The problem is when I send these requests through XHR, the browser always sends the Origin header with the request. For the first request I described above, onedrive also replies with an Access-Control-Allow-Origin:* header, so the request is allowed in the browser. However, when the browser is redirected to the actual location of the file, that resource does not have the Access-Control-Allow-Origin header, so the XHR request is denied by the browser(chrome sends an Origin header set to null for the redirect request).
I've also tried getting the location but not redirecting automatically, and then sending another XHR request, this will set the origin header to the domain of my site, but the result is the same.
As I mentioned in the beginning, I need to process the data in javascript, so I'm not asking about how to download onedrive files to hard drive. I need the data to be accessible by javascript in the webpage.
I know that I can use server side programming to get the file data for me and then send it to the client, but for my application this is not an option(at least this is not what I'm asking for at the moment).
If there is no way to do this, does anyone have an idea why they would implement their api this way? To allow javascript to get the location through cors and redirect but not include a cors header for the redirected resource. Why not just deny cors in the first place? Is this a bug?

The answer, as best as I can tell, is that downloading content cannot be done purely by JavaScript in a browser. Why did they do it this way? You'd have to ask them, but I would guess either a bug, or some unspecified "security concerns". For what it's worth, they seem to think that downloading content is CORS compliant in the documentation here: https://dev.onedrive.com/misc/working-with-cors.htm:
To download files from OneDrive in a JavaScript app you cannot use the
/content API, since this responds with a 302 redirect. A 302 redirect
is explicitly prohibited when a CORS preflight is required, such as
when providing the Authorization header.
Instead, your app needs to select the #content.downloadUrl property,
which returns the same URL that /content would have redirected to.
This URL can then be requested directly using XMLHttpRequest. Because
these URLs are pre-authenticated they can be retrieved without a CORS
preflight request.
However, to the best of my knowledge, they are wrong. Just because you don't need a preflight request doesn't mean that the response is CORS-compliant. You still need an Access-Control-Allow-Origin header on the response.
For anyone wondering, this is still an issue in the new Graph API (which is essentially a proxy API to the OneDrive API, as I understand it). The same basic issue is still present - you can get a download URL from your items, but that URL points to a non-CORS-compliant resource, so it doesn't do you a whole lot of good.
I have an active issue open with Microsoft here about this issue. There has been some response to my issue (I got them to expose the download URL through the graph API), but I'm still waiting to see if they'll come up with a real solution to downloading content from JavaScript.
If I get a solution or real answer on that issue, I'll try to report back here so others in the future can have a real answer to reference.

This is not an answer, I cannot comment yet.
Last week the new API for onedrive was released. http://onedrive.github.io/index.htm
Unfortunately it will not solve the problem.
https://api.onedrive.com/v1.0/drive/root:{path and name}:/content?access_token={token}
Will still redirect to a ressource somewhere at https://X.files.1drv.com/.X.
Which will not contain any Access-Control-Allow-Origin headers. Same goes for the Url "#content.downloadUrl" in the JSON response.
I hope that microsoft will address this problem in the very near future, because the API is at the moment of very limited use, since you cannot process file contents from onedrive with html5 apps. Apart from the usual file browser.
The only solution, which I see at the moment would be a chrome app, which can process the Url without CORS. see https://developer.chrome.com/apps/angular_framework

Box does exactly the same thing for download requests. I have not found any way around this problem without involving a server because the browser will not let your program get access to the contents of the 302 redirect response. For security reasons I am not convinced of, browsers mandatorily follow redirect requests without allowing user intervention.
The way we finally worked around this was
the browser app sends the GET request to the server which forwards it to the cloud provider (box/ondrive).
server then DOES NOT follow the 302 redirect response from Box or OneDrive
The server instead returns to the browser app, the content of the location field in the 302 response header, which contains the download url
The javascript in the browser app then downloads the file using the url.

You can now just use the "#content.downloadUrl" property of the item in your GET request. Then there is no redirection.
From https://dev.onedrive.com/items/download.htm:
Returns a 302 Found response redirecting to a pre-authenticated download URL for the file. This is the same URL available through the #content.downloadUrl property on an item.

Related

Sending cookies automatically in cross-origin XHR requests

I've developed a plugin for a web site, for the sake of this post let's call it www.somesite.com
The plugin has authorization page on my website, let's call it www.mysite.com, which returns cookie upon authorization, which I obviously want to use in subsequent requests to www.mysite.com.
The plugin uses dynamic rules to change Access-Control-Allow-Origin on request to www.somesite.com to "*", so cross-origin requests can be sent from the page to www.mysite.com. However cookies of www.mysite.com are not passed automatically with the request when I send requests from plugin's injected code using XMLHttpRequest. As I understand this is intended browser behavior to prevent "stealing" cookies via cross origin requests, and cookies are only passed if the request is originated from the browser itself.
Question is, is there a way around this? Obviously I'm not trying to steal your cookies :) I just need the cookies of www.mysite.com to be sent automatically in XHR requests I send from the webpage on www.somesite.com domain.
I've seen a similar question, but it required to modify response headers of the origin site, which I obviously have no access to, so in my case that solution won't work. I have access to backend of www.mysite.com, front end of www.mysite.com, frontend of www.somesite.com (via script injection via plugin) and NO ACCESS to backend of www.somesite.com.
Thanks!

Swagger fails with CORS-style error

Can't read from server. It may not have the appropriate access-control-origin settings.
I've had this error before, but I could really do with having Swagger UI work this time. The json file I'm putting the URL in for is being served from the same host, so it shouldn't require CORS. Indeed I've enabled CORS on the server side but it's not adding the headers because the browser isn't sending an Origin header (presumably because it knows CORS isn't required).
In fact the json file returns a 200 and I can see the content of it in the response in the Chrome debug tools network tab - infuriatingly there isn't a failed request in there so I don't know what's broken, other than that the petstore URL does work.
ETA: Swagger Editor can call my API without these issues, even when it is hosted on another server, but it's Swagger UI I want to share with users.
It was nothing to do with CORS, whatever the issue was.
Replacing the JSON file with one taken from the petstore worked, so it must've been some issue parsing it.

Cross domain AJAX requests are not being blocked: is this a security vulnerability?

I spent the last 3 days studying how to make a cross domain request using XMLHttpRequest. The best alternative is indeed with JSONP which I am already using.
But I still have a question that I could not find answer nowhere. I read hundreds of posts (including SOs) and nobody has a good liable answer (with nice reference). Hope someone here can help.
Said that, I read in many websites that due to security reasons I cannot make an Ajax request from domain example.com to yyy.com and get the data I want. It's very clear and I have no question about that. BUT the problem is when I run the code below in my localhost (so my domain is "localhost" and I should not me able to request any data from another domain).
xhReq = new XMLHttpRequest();
xhReq.open("GET","http://domain.com.br?parameter",true);
xhReq.send(null);
When I inspect the Firebug Net Tab I realize that the request was not blocked! It was clearly requested. I could not believe. So I created a file in the domain.com.br/log.php where I could log any request that hit my domain. Surprisingly all the requests I was firing localhost were hitting my domain.com.br. When I tried to fetch the response I really could not get it due the same origin policy of my Chrome and FIrebug browser. But I was reallyl surprised that the request really hit the webserver despite I could no manipulate the responde.
More surprisingly is that if domain.com.br/log.php generates a huge responde with like 1MB my firebug showed me that the browser does download ALL th 1MB from the webserver, and at the end it shows a message "Access denied" as expected. So why download all the file if the same origin policy forbids that data to be read.
Finally, I makes me amazed, is that all the websites and specifications I read says very CLEAR that the request is blocked using Ajax when the target domain does not match the source domain. But clearly, with my experiment, the requests are being completed, despite I cannot have access to the response data.
What makes me upset is that it could be open a BIG security hole, in which a website with thousands of views everyday could run this 3 line code and cause a HUGE Ddos attack in an unfriendly website just making the users request a page in another website in small intervals since the browser will not block the request.
I tested this script in IE 7, 8 and 9 and Chrome latest and Firefox latest and the behaviour is the same: the request is done and the browser downloads all the response while not making it avaiblable to do SOP.
Hope someone can explain me why the specs are so wrong about it or what I am understanding wrong!
The request can be made, and the server may generate a response, regardless of CORS. However, the response may be hidden. balpha wrote about this in his blog recently:
Note that the same origin policy doesn't necessarily prevent the request per se – it just prevents the response from being accessible. A malicious site can e.g. just redirect your browser, or submit a form, or include an image or an iframe – in all those cases a request is made to your site; the evil site just doesn't see the response.
To some extent, the browser has to make a request to the server to see if it servers an "Access-Control-Allow-Origin" header. Remember that CORS is completely implemented by the browser. Someone could just write a console application to make a request to your server, so you shouldn't rely on CORS to make sure requests are only coming from your own site.
You can achieve the same effect (like a dos attack you said) with a simple image file, it does not necessarily need to be XHR. Link an image file from a different website, put millions of it in your page, display it to your users and boom.

Using FineUploader with optional https?

I have setup FineUploader on a site and I included a check box that allows users to upload files using HTTPS if the want to.
Unfortunately if the user accesses the site using http and then tries to use ssl it errors out, I assume because of CORS issues. I assume it is a CORS issue because if I access the site using https and try to upload using ssl it works fine.
I found some documentation about enabling CORS support, but it appears that you either need to make it so only CORS requests will be made or none will be made. In my situation there will be CORS request some times and not others.
Does anyone know of a good work around for this? Should I just reload the entire page using HTTPS when the checkbox is clicked?
If you're uploading straight to Amazon s3, see the note in the official docs, "SSL is also supported, in which case your endpoint address must start with https://" in the script within your uploaderpage.html file.
request: {
endpoint: 'https://mybucket.s3.amazonaws.com',
// Note that "https://" added before bucket name, to work over https
accessKey: 'AKIAblablabla' // as per the specific IAM account
},
This will still work if uploaderpage.html is served over http (or you could populate the endpoint value dynamically if you need flexibility re endpoint).
This will help you avoid the mixed content error when uploading over https, "requested an insecure XMLHttpRequest endpoint", which happens if the page is https but you request a http endpoint.
Just to reiterate what I've mentioned in my comments (so others can easily see this)...
Perhaps you can instantiate Fine Uploader after the user selects HTTP or HTTPS as a protocol for uploads. If you must, you can enabled the CORS feature via the expected property of the cors option. Keep in mind that there are some details server-side you must address when handling CORS requests, especially if IE9 or older is involved. Please see my blog post on the CORS feature for more details.

Javascript check web server HTTP status code

Is there anyway with javascript/jQuery to check if a website is up?
You're limited by the single origin policy I don't think you can use a standard Ajax request, but is it possible to try and load a file (similar to wget) and get the status code of the reply another way?
This would be for a user side website checker, where they can check if multiple domains are "up" without having to use any code on a server.
e.g. I open a web page at checkmysite.org it sends an HTTP request to mysite.org to check whether it receives a response, and if so the domain is online
The single origin policy exists for a very good reason. What you're asking is effectively the same as "how can I defeat the single origin policy?".
You could always work around the policy with the co-operation of the server-end, for some specific known server. (e.g: CORS, cross-domain.xml in flash, <script> tag, etc).
Why is it so important that this not have help from the server at checkmysite.org? It could host an absolutely trivial php script which does the HEAD request for you. Your JavaScript code could just do a normal GET request to the PHP script.

Categories

Resources