Enabling cross domain scripting in the intranet - javascript

I'm having a few problems with an application that integrates sharepoint, SQL reporting services and a bunch of custom forms that are built using ASP.NET MVC.
Assuming my servers are as follows;
MOSS
SSRS
Custom forms
In MOSS, my portal has need on occassion to popup a custom form to capture user input. I've done this by using a jQuery dialog (using Boxy), which iframes the custom form in and passes the url of the portal into it. When the custom form is finished, it navigates the parent window (the MOSS portal) to the URL passed in, which effectively refreshes the page.
This was working fine until we threw in the complexity of SSRS.
Now in MOSS, I have a report that lists some data, but the SSRS report viewer web part seems to iframe it's report content in, which means the hyperlinks from the report can't ask the parent to overlay the same dialogs (as it's cross domain) and if it were to perform the overlay itself, it would just overlay the iframe.
Sorry for the long post, getting to the point - this is an internal intranet application only. Is it possible to allow cross domain scripting somehow so that the popup dialogs can all be controlled from javascript within the sharepoint portal and SSRS and my custom forms can just invoke javascript methods on the parent?
Preferably I wouldn't want to have to do configuration in the client browser to allow this to happen, as I'd have to roll that change out to all the machines within the estate - which is a significant number.
Thanks in advance, beer available to anyone who can solve my woes ;)
Cheers,
Tony

IE8, Firefox 3, recent Opera and Safari/Chrome support postMessage which allows cooperating pages on different domains to talk to each other:
http://ajaxian.com/archives/cross-window-messaging-with-html-5-postmessage
If you are stuck with older browsers, you have few options. The cleanest is to send everything that needs to communicate with each other through the same proxy, although in the OP's situation it looks like this isn't possible.
The next cleanest is to use Flash's cross-domain facility.
Another option is xssinterface, which wraps postMessage where available and uses some voodoo involving cookies and polling where it isn't.
The only other option is to use hidden iframes - to send a message to a page, change the iframe's location to one on the destination page's domain and poll in the destination page - but again I think the proxying in the OP's case makes this unworkable.

There is another option in addition to those Andrew provides. You can dynamically inject script tags into the DOM, wherein the src attribute can point to a javascript file on any domain.
In jQuery you accomplish this by specifying "jsonp" as the datatype for the ajax request. You can read more about this approach here:
http://blog.ropardo.ro/2009/09/23/cross-domain-ajax-calls/

I finally got around these issues by using hidden iframes as suggested. I posted an article on my blog with more details and pushed the code onto codeplex:
http://www.deepcode.co.uk/2009/11/overcoming-cross-domain-issues-between.html

Related

iframe not active unless receives user interaction

I've been working on a requirement that involves a website fetching/manipulating data stored on a different domain. There didn't seem a way except for enabling CORS on the other server to allow me to get and modify data from a different domain. However, that caused some issues with Office 365 apps and I had to take a different approach.
The approach is to use postMessage to talk to a hidden iframe (not a good approach, but I was insisted to use it) on the page that is running on the target domain. The source page posts message along with information about the REST call to the hidden iframe which makes a requests on behalf of the parent page and uses postMessage to return back the results.
Everything works fine except for when the website is being used on an iPhone. Turned out placing alert calls in the script running inside the target iframe makes it to work but removing the alert calls sort of disables the target iframe from making those cross-origin network calls.
My theory is that it is due to the security of mobile Safari that in order to make cross-origin calls from an iframe running on a different domain, the user needs to provide their consent by interacting at least once with the embedded iframe. Does that sound correct?
The comment by diodeus-james-macfarlane is the closest that we could go but the iframe being hidden, there was no way we could have placed a control for the user to interact with, even if that was only for it to work.
To my surprise, turning off a setting on the SharePoint site made it work. The setting was around mobile view compatibility and without that, the iframe is able to make HTTP requests, send and receive messages to and from the parent webpage.

Improve the usability of 3rd party application

A 3rd party application we use is causing a great deal of issue because the user isn't clicking a Register button prior to clicking the Launch button or if they do click Register first, this Details page with both Register and Launch buttons refreshes and goes to their portfolio. They have to then re-find that item in their protfolio list.
The 3rd party application I believe is a .NET and is using knockout.js and does not allow embedding in Frames.
What are some options for providing guidance to the user or ideally make this process less painful?
I was hoping to provide an internal webpage that could send both Request and Launch actions with a single button click. I posted an earlier question Knockout data-bind click but couldn't get something to work.
There seems to be a bunch of similar questions on SO but I am not sure if these questions/answers are for automating button clicks on self contained applications as I want to do it if from outside the 3rd party application (do I even have access to their view model?). This app prevents embedding it in Frames.
Auto-click button element on page load using jQuery
How to auto click button in knockout js
Currently I have a link from internal website that opens two browser windows side by side. One goes to 3rd party and 2nd window with instructions. This is OK but we found people don't want to read. I really want to have a single button click or at least be able to send one request at a time from the internal webpage. Or perhaps overlay a joyride type guidance onto their site, if possible.
Here is the 3rd party button code
<a class="btn btn-large btn-blue" href="javascript:void(0);"
data-bind="click: $root.clickAction.bind($data, ActionType)">
<span data-bind="text: Title">Register</span></a>
You basically want to hack the 3rd party app, but you control the environment, so it doesn't sound impossible. (I won't talk about whether I think it's a good idea, I will just list a few options you may have.)
Removing the X-Frame-Options header
You are saying the 3rd party app does not allow to be embedded in a frame. That is done by a response header, most probably X-Frame-Options (or it can be Content-Security-Policy: frame-ancestors, but it doesn't actually matter). All you have to do is remove that header and voila, the app can be loaded in a frame.
To remove the header, you will need some kind of a proxy. If the app is served on plain http, it is really easy, any kind of http proxy can remove the appropriate response header. If it is served on https, you have to do a few things to actually make it work (create a certificate authority, add the root cert to clients as trusted root, use the proxy to connect to the app and besides removing the header, replace the https cert with your own, which will then be trusted on your clients).
Note that this will weaken the security of the 3rd party app and it will make it vulnerable to attacks similar to clickjacking (and also pixel perfect timing and so on, all frame related attacks).
Inject custom script via proxy (edit: added this later)
With a proxy as described above, you don't need to remove X-Frame-Options. It's much better to inject your own javascript into the 3rd party application page, which can do whatever you want on the original page as it has full access to the application DOM. For instance it can change behaviour so that the appropriate buttons are clicked. :) I would do this if I wasn't able to install a browser extension on clients (see below).
Using a custom client
Instead of using the browser as the client, you could make a custom client that in practice acts as a browser, but disregards the above headers. This could also do the clicks you want without much hassle. The drawback is your users would have to start the custom client instead of using their browser to use the application. This is probably easier to do in a mobile environment where you have things like Xamarin and WKWebView.
Browser extension
An easier and probably more feasible variation on the custom browser idea is a browser extension. It could activate on the application url, and it could very easily do the clicks you want on the appropriate pages (browser extensions can request full access to pages regardless of headers). You would only have to install the extension once on clients. I would probably do this if I had to.

What are the -interactive- alternatives to IFrames

Well met!
I am working on a project similar to the Windows 8 tile-interface, only for Websites.
The idea is that, when a tile is clicked, it grows to fill the site (leaving a menu-bar on the top free) and the user can reguarly browse the loaded site. When he clicks a button on the menu-bar, the tile grows back.
My approach was to use IFrames. But those can be disabled through a HTTP-option by the visited site, or by using some javascript to test window toplevel.
Therefore I need some kind of alternative to IFrames. The best thing I was able to find was the JQuery .load(url), which only displays the content of the site, not making it regulary useable. It was very slow in my tests, too.
Is there something I can use, or do I have to drop the idea?
Thanks in advance!
Loading resources from different origins is very limited on the client side. Your best bet is probably a proxy on the server side (which isn't a perfect solution as it's used by scammers, read about it carefully) - I remember this iPad simulator has a fake Mobile Safari browser which uses php simple proxy.
Using Client Side Technology ...
jQuery's .load() will fetch the resource using AJAX and is constrained by the same-domain origin policy (security sandbox) that is inherent to the XMLHttpRequest object.
an iFrame will load the resource but as you pointed out it has drawbacks.
Using Server Side Technology ...
if you have only a few websites in the tiles that will need to be opened, you could preload them using a server side technology (php, jsp, asp) and hide them in a container object (like a div element) and then programmatically show them when the user activates the tile though a hover or click event.
Using java for example, you could use the java.net library to open a string buffer, read and save the contents of the website, and then add the variable to the servlet response. Using JSTL you would output the variable from the response object.

Alternatives to iframe for loading cross-site HTML when using iPhone?

I apologize if this has been asked before. I searched but did not find anything. It is a well-known limitation of AJAX requests (such as jQuery $.get) that they have to be within the same domain for security reasons. And it is a well-known workaround for this problem to use iframes to pull down some arbitrary HTML from another website and then you can inspect the contents of this HTML using javascript which communicates between the iframe and the parent page.
However, this doesn't work on the iPhone. In some tests I have found that iframes in the Safari iPhone browser only show content if it is content from the same site. Otherwise, they show a blank content area.
Is there any way around this? Are there other alternatives to using iframes that would allow me to pull the HTML from a different domain's page into javascript on my page?
Edit:
One answer mentioned JSONP. This doesn't help me because from what I understand JSONP requires support on the server I'm requesting data from, which isn't the case.
That same answer mentioned creating a proxy script on my server and loading data through there. Unfortunately this also doesn't work in my case. The site I'm trying to request data from requires user login. And I don't want my server to have to know the user's credentials. I was hoping to use something client-side so that my app wouldn't have to know the user's credentials at the other site.
I'm prepared to accept that there is no way to accomplish what I want to do on the iPhone. I just wanted to confirm it.
You generally can NOT inspect the contents of an iframe from another domain via JavaScript. The most common answers are to use JSONP or have your original server host a proxy script to retrieve the inner contents for you.
Given your revisions, without modification or support from the secondary site, you are definitely not going to be able to do what you want via the iPhone's browser.
"In some tests I have found that iframes in the Safari iPhone browser only show content if it is content from the same site"
I found the same thing. Is this documented somewhere? Is there a workaround? This sounds like broken web standards to me, and I am wondering if there is a solution.

Embedding web controls across sites - using IFrames/Javascript

I'm just looking for clarification on this.
Say I have a small web form, a 'widget' if you will, that gets data, does some client side verification on it or other AJAX-y nonsense, and on clicking a button would direct to another page.
If I wanted this to be an 'embeddable' component, so other people could stick this on their sites, am I limited to basically encapsulating it within an iframe?
And are there any limitations on what I can and can't do in that iframe?
For example, the button that would take you to another page - this would load the content in the iframe? So it would need to exist outwith the iframe?
And finally, if the button the user clicked were to take them to an https page to verify credit-card details, are there any specific security no-nos that would stop this happening?
EDIT: For an example of what I'm on about, think about embedding either googlemaps or multimap on a page.
EDIT EDIT: Okay, I think I get it.
There are Two ways.
One - embed in an IFrame, but this is limited.
Two - create a Javascript API, and ask the consumer to link to this. But this is a lot more complex for both the consumer and the creator.
Have I got that right?
Thanks
Duncan
There's plus points for both methods. I for one, wouldn't use another person's Javascript on my page unless I was absolutely certain I could trust the source. It's not hard to make a malicious script that submits the values of all input boxes on a page. If you don't need access to the contents of the page, then using an iframe would be the best option.
Buttons and links can be "told" to navigate the top or parent frame using the target attribute, like so:
This is a link
<form action="http://some.url/with/a/page" target="_parent"><button type="submit">This is a button</button></form>
In this situation, since you're navigating away from the hosting page, the same-origin-policy wouldn't apply.
In similar situations, widgets are generally iframes placed on your page. iGoogle and Windows Live Gadgets (to my knowlege) are hosted in iframes, and for very good reason - security.
If you are using AJAX I assume you have a server written in C# or Java or some OO language.
It doesn't really matter what language only the syntax will vary.
Either way I would advise against the iFrame methods.
It will open up way way too many holes or problems like Http with Https (or vice-versa) in an iFrame will show a mixed content warning.
So what do you do?
Do a server-side call to the remote site
Parse the response appropriately on the server
Return via AJAX what you need
Display returned content to the user
You know how to do the AJAX just add a server-side call to the remote site.
Java:
URL url = new URL("http://www.WEBSITE.com");
URLConnection conn = url.openConnection();
or
C#:
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://www.WEBSITE.com");
WebResponse res = req.GetResponse();
I think you want to get away from using inline frames if possible. Although they are sometimes useful, they can cause issues with navigation and bookmarking. Generally, if you can do it some other way than an iframe, that is the better method.
Given that you make an AJAX reference, a Javascript pointer would probably be the best bet i.e. embed what you need to do in script tags. Note that this is how Google embed things such as Google Analytics and Google Ads. It also has the benefit of also being pullable from a url hosted by you, thus you can update the code and 'voila' it is active in all the web pages that use this. (Google usually use version numbers as well so they don't switch everyone when they make changes).
Re the credit card scenario, Javascript is bound by the 'same origin policy'. For a clarification, see http://en.wikipedia.org/wiki/Same_origin_policy
Added: Google Maps works in the same way and with some caveats such as a user/site key that explicitly identify who is using the code.
Look into using something like jQuery, create a "plugin" for your component, just one way, and just a thought but if you want to share the component with other folks to use this is one of the things that can be done.

Categories

Resources