Client-side secure mashups

IBM® WebSphere® sMash includes the secure mashup provider for the Open Ajax Hub for developing secure client side mashup applications.

Introduction to secure client side mashups

Client side mashups mix and merge content (data and code) from multiple content providers inside the same page. The existing browser security model was not designed for supporting such applications, and therefore they are typically implemented in an insecure manner. This article, describes a secure component model, where components are provided by different trust domains, and can interact using a communication abstraction that allows ease of specification of security policy.

WebSphere sMash implements the draft specification of the Open AJAX Hub 1.1 API and includes the reference hub providers (inline and smash) to allow mashable components to interact with each other. WebSphere sMash however does not include a complete Open AJAX implementation. Since the Open AJAX Hub 1.1 API is in the draft stage and is expected to change, this implementation and API has been deprecated in favor of a more complete implementation that will be available in a follow-on release. By virtue of the virtual directory feature of WebSphere sMash it should be possible to drop in a Open AJAX implementation in the public folder of the application to leverage features of Open AJAX as they become available.

The component abstraction in the smash provider is realized using the HTML <iframe> element, which was designed as a container for loading sub-documents inside the main document. Some technical challenges that were addressed are:

  1. Enabling parent to child document communication links when the parent and child are from different trust domains
  2. Guarding against component phishing, where an untrusted component in a mashup can change which component is loaded in another part of the mashup
A future goal of this technology is to be able to specify and enforce security policies to ensure that integrity, confidentiality and privacy of information on these links.

Adding secure client mashup capabilities to your IBM® WebSphere® sMash application

To add this capability to your WebSphere sMash application, you need to add the following dependency to the application's config/ivy.xml file.

<dependency name="openajax.hub" org="zero" rev="1.1+"/>

Open Ajax hub references

The best sources of information for Open Ajax hub and the SMASH provider can be found at the following locations:

Using the Open AJAX Hub to create a mashup application

The mashup application typically consumes one or more third party mashable components and interacts with them through the Open AJAX hub. The code samples used in this section of the article are associated with the openajax.demo sample described in the SAMPLES section of the developer's guide.

The mashup application needs to initialize itself with the Open AJAX Hub API and will include any mashable components using IFrames. The following code sample shows an example of the mashup or parent container application using an IFrame to include a mashable component from the employee.resource.openajax.demo application described in the following section.

<script src="openajax/OpenAjax.js"></script> <script src="openajax/OpenAjax-mashup.js"></script> <script src="openajax/providers/smash/json2.js"></script> <script src="openajax/providers/smash/smash.js"></script> <!-- Actual Application --> <script type="text/javascript"> var theTopic="employee.resource"; var myName = "employee.resource.provider"; var subHandle = null; var csubHandle = null; function errorCallback(clientName, errormsg) { alert("client: " + clientName + " error message:" + errormsg); } function loadFrame(uri, parentElement) { var iframe = document.createElement("iframe"); // set defaults iframe.style.width="100%"; iframe.style.height="100%"; iframe.style.border="none"; iframe.src = uri; parentElement.appendChild(iframe); return iframe; } var iframeC1 = null; var parentElementC1 = null; var iframeC2 = null; var parentElementC2 = null; var tunnelURI = "openajax/providers/smash/tunnel.html"; function init() { smash.configure({tunnelURI: tunnelURI}); // load the components parentElementC1 = document.getElementById("c1"); var uriC1 = parentElementC1.attributes["src"].value; uriC1 = smash.prepareForLoad({clientName:"c1", uri: uriC1, commErrorCallback: errorCallback}); iframeC1 = loadFrame(uriC1, parentElementC1); parentElementC2 = document.getElementById("c2"); var uriC2 = parentElementC2.attributes["src"].value; uriC2 = smash.prepareForLoad({clientName:"c2", uri: uriC2, commErrorCallback: errorCallback}); iframeC2 = loadFrame(uriC2, parentElementC2); }

This application uses another IFrame to render a form with a text box, whose value will be published to the employee.resource topic on the hub. It renders any message received on the employee.resource.results topic.

<body onload="init()"> <!-- Remote component --> <span id="c1name"></span> <div style="width: 500px; height: 200px; border-style: solid;" id="c1" src="http://localhost:8080/openajaxwrapper.html"></div> <!-- Local component --> <span id="c2name"></span> <div style="width: 500px; height: 200px; border-style: solid;" id="c2" src="http://localhost:7800/name_search.html"></div> </body>

The src attributes of the <div> tags in the above code sample indicates the location of the components. Both the components have to register with the Open AJAX hub and use the hub api to interact with each other. The name_search.html may for instance look like the following.

<html> <head> <script src="openajax/providers/smash/json2.js"></script> <script src="openajax/providers/smash/smash.js"></script> <!-- Application logic --> <script type="text/javascript"> var theTopic="employee.resource"; var myName = "c2:"; var connHandle=null; var subHandle = null; var csubHandle = null; var counter=0; function connectCallback(success, handle) { connHandle = handle; connHandle.setSecurityErrorCallback(errorCallback); // subscribe to the only channel resubscribe(theTopic); } function init(){ connHandle = smash.connect({callback: connectCallback}); } function channelListener(subHandle, topic, message) { if (topic == "employee.resource.results") { var res = "Not Found!"; if (message[0]) { res = message[0].firstname +" "+message[0].lastname; } document.getElementById("result").innerHTML = res; } } function sendMessage(topicName) { var emp = document.getElementById("employee").value; connHandle.publish (topicName, {sender: myName, content: ( emp )}); counter++; } function unsubscribe() { subHandle.unsubscribe(unsubscribeCallback); } function resubscribe(topicName) { connHandle.subscribe(topicName, subscribeCallback, channelListener); } </script> </head> <body onload="init()"> <p>Employee Search</p> <span id="c2div" ></span> <p> employee: <input type="text" size=20 id="employee" value="Joe E Public" /> <input type="button" onclick="sendMessage(theTopic);" value="Search thru Employee Resource"> <p> <span id="result"></span> </body> </html>

Using the Open AJAX Hub to create a mashable component

The mashable component or widget is the trusted or untrusted third party component that will be consumed by the mashup application. The component interacts with the mashup application and its components using a publish-subscribe paradigm using the Open AJAX hub provider(SMASH). The code samples used in this section are associated with the employee.resource.openajax.demo sample described in the SAMPLES section of the developer's guide.

The mashable component from trusted or untrusted third-party sources should be coded to the Open AJAX Hub API. The following code fragment shows the initialization of the provider in WebSphere sMash

<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="openajax/providers/smash/json2.js"></script> <script src="openajax/providers/smash/smash.js"></script> <script type="text/javascript"> var theTopic="employee.resource"; function connectCallback(success, handle) { connHandle = handle; connHandle.setSecurityErrorCallback(errorCallback); // subscribe to the only channel resubscribe(theTopic); } function init(){ connHandle = smash.connect({callback: connectCallback}); }

In this example, the mashable component recieves a text string which it uses as a search parameter in a XHR request for a RESTful service associated with the component. The component subscribes to a well known topic employee.resource and recieves the search parameter as a notification when some other component publishes to that topic. The service returns the search results in the form of JSON data. This data is then published to the Open AJAX hub using the employee.resource.results topic.

function channelListener(subHandle, topic, message) { if (topic == theTopic) { document.getElementById("empsearch").innerHTML = message.content; var res = searchFor (message.content); } else { // this will not happen with the real open ajax hub console.debug ("Not my topic: "+topic); } } function resubscribe(topicName) { connHandle.subscribe(topicName, subscribeCallback, channelListener); } var employeeURL = '/resources/employees'; function searchFor (name) { var param = "/resources/employees?firstname__contains="+name; var req = dojo.xhrGet({ url: param, handleAs: 'json-comment-optional', sync: false }); req.addCallbacks(sendResults); } function sendResults(response){ document.getElementById("empsearch").innerHTML += "... Done" connHandle.publish("employee.resource.results", response); }
<body onload="init()"> <p>employee.resource</p> <span id="c1div" ></span> <p></p> <p>Searching for: <span id="empsearch"></span> </body>

Version 1.0.0.3.25591