I would like to know if there is a way to intercept the image loading requests of a browser and add some request headers expected by the server.
The actual scenario is this. The web app sends an XHR to the server and completes an authentication handshake. All the subsequent requests have to include the auth header. The images are broken because the browser does not send the headers for the image requests.
Thanks in advance.
You can request the image using AJAX with the appropriate headers. Then you must base64 encode the image binary and insert it into the DOM by setting
<img src="data:image/png;base64,[base64 encoded image]" />
There is a way to intercept image requests in the browser: checkout the Capturing API in Mobify.js: https://hacks.mozilla.org/2013/03/capturing-improving-performance-of-the-adaptive-web/
No, there is not a way to do that, and it's a very good thing too.
(Well, there's no way to do it from your code. The browser owner can install a tool that alters requests if they so desire, of course.)
The fact that browsers issue HTTP requests for scripts and images in their own strict ways means that a site using XHR can prevent some kinds of CSRF attacks (cross-site request forgery) by having the server refuse certain requests if they don't include a special header that the site's own XHR code adds.
You can't control exactly what a browser does to the header with form posts, either.
Related
I recently found (here: Does every web request send the browser cookies?) that every HTTP request contains the cookies related to a domain every time a request is made to that same domain.
Given this, what happens when the request is not sent through a browser but from Node.js, for example? Is it possible that no information is sent in the request?
Is it also possible to prevent it to be sent in the browser requests?
Browsers
Is not possible to prevent browser to send cookies.
This is why is generally it is recommended (Yahoo developer Best practice, see section Use Cookie-free Domains for Components) to serve static content like css, images, from a different domain that is cookie free.
When the browser makes a request for a static image and sends cookies together with the request, the server doesn't have any use for those cookies. So they only create network traffic for no good reason. You should make sure static components are requested with cookie-free requests. Create a subdomain and host all your static components there.
Programmatically
From any programming language, instead, you can choose if you like to send cookies or not.
Cookie management is done by the programmer, because libraries are written to make single requests.
So if you make a first request that return cookies, you need to explicit read them, hold them locally somewhere, and eventually put them in a second request to the same server if you need.
So from NodeJS if you don't explicitly add cookies in your requests the http call doesn't hold them.
You Can Use Fetch with the credentials option set to omit
see
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
You can strip cookies with a proxy server. For example our product WinGate will allow you to modify requests (and responses), and you could use this to clear the Cookie header in requests.
However, this will prevent a large number of websites from functioning properly, as cookies are used to transport session IDs so that the server can identify each connection / request your browser makes as being from the same "session". HTTP itself does not have any concept of session.
Disclaimer: I work for Qbik who make WinGate.
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.
Is there a programmatic way in javascript to ignore cookies sent from the server (without changing browser settings).
We use certain plugins on our web server that will randomly update our security cookie. However this causes issues for some of our URLs and we want to ignore those cookies for some cases.
Our security architect recommended we look into this possibility.
example:
1). create ajax request with URL: www.site.com/abc/comtd
2). ignore any cookies that come back in the response
The only way I can think of is to send the AJAX request from a completely different domain. Because the AJAX would be a Cross-Origin Resource Sharing (CORS) request, any response headers would be denied unless the server sends the access-control-allow-origin header. If the AJAX request is not a CORS request, the browser has to respect all Set-cookie headers it receives per the standard.
its not an option in our case to change domains. We need to pass cookies to the server or the requests will not get through security. If we change domains our security cookies would not get passed. What we want is to pass the cookies but ignore any set-cookie response headers for certain URLs.
I think this is not possible on the browser so I am investigating some Apache server plugins like mod_headers. Maybe we can do it on the server itself. Im closing this question and will open another one related to mod_headers.
Just a thought - if you send the request from a WebWorker - I think that is isolated from the main browser context ?
I'm trying to detect server information using only JS such as HTTP response code & content.
Because of Same-origin policy I'm not allowed to use normal ajax request and therefore i'm forced to following workarounds
Using JSONP is great but in case of error I can't know what HTTP code or content of response page
Using Image request is not really option cause, same as above, I can't know HTTP code or content. I can only know if I loaded image to DOM.
Using AJAX with CORS. This is best solution so far but in case it is not my server I can't detect HTTP code :(. Same applies for flash and crossdomain.xml policy.
Using iframe, as i know I can't detect HTTP code or content.
While writing this I've just notice that I'm dealing with XSS issues here but all I need from JS is HTTP code OR content of another domain.
All suggestions are welcome.
I fear that is not possible using client-side JavaScript, unless the server implements a mechanism allowing you to gather this information by either simply supporting CORS or include the information in the JSON response of the JSONP request.
However, if you have some server-side support you could put in place an API that allows you to do so. E.g. You call a service on your server which in turn performs the request on the remote server and returns the desired information.
When using an XMLHTTPRequest in javascript, I want to send it to an external website, rather than the one where the .js file is hosted. To send it to test.php on the current server, I would use
request.open("POST", "test.php", true);
but for the second arguemnt, how do I send it to another website. "example.com/test.php" looks for a file on the current server, and "http://example.com/test.php" justseems to outright fail.
You can't for security reasons. See the same origin policy for JavaScript.
There are some workarounds that exploit browser bugs or corner cases, but using them is not recommended.
The best approach is having a server-side proxy that receives Ajax requests, and in turn, sends HTTP requests to other servers. This should be carefully implemented by sanitizing input and whitelisting the types of requests that are sent, and the servers that are contacted.
This sounds like a bad case of Same Origin Policy, my friend :)
You can't (for the most part) use XmlHttpRequest to get data from an external website. What you can do, however, is dynamically create a SCRIPT tag and reference an external address. jQuery wraps this functionally as part of its ajax handling.
Indeed you can. Not in any browser although.
In Internet Explorer 8.0 there is XDomainRequest, an object enabling cross-domain requests. You would need to properly handle request made with this object on server by sending Access-Control-Allow-Origin header first with "*" or requester domain name.
Since you are doing some hacky things anyway, why not trying to use it on IE8 first?
If you have control over the server, you can use this header in the HTTP reply, although it may not work with all browsers.
Access-Control-Allow-Origin: *