By default Silverlight applications are allowed to access resources (services) only from the location from where they originated. From Silverlight 2.0 support was included to access services from a remote server (cross-domain), as long as the remote server allows the Silverlight application to access it. This gave administrators more control on who is accessing the resource, and can impose certain restrictions.
The security policy system in the Silverlight runtime requires that a policy file (clientaccesspolicy.xml) be downloaded from a target domain before a network connection is allowed to access a network resource under that target domain.
When a connection request is initiated from Silverlight application, the SL runtime tries to download the security policy file using the HTTP protocol. The SL runtime first tries to download a SL policy file with the name "clientaccesspolicy.xml" at the root of the requested target domain using HTTP protocol. If it can't find "clientaccesspolicy.xml" file, it will try and download "crossdomain.xml" file, which was developed by Adobe for Flash. Both the files are recognised by SL runtime.
If the policy file retrieved is successfully parsed and grants permission, a connection is finally opened to the target host. If the policy file retrieved is invalid, the connection to network resource is denied by SL runtime. For more information on policy file please refer to http://msdn.microsoft.com/en-us/library/cc645032(VS.95).aspx
Challenge with AppFabric Service bus
From the above AppFabric Service bus architecture picture, we can imagine your SL application is running on the LHS (on-premises). The WCF services that the SL application dependant on is deployed on the RHS (on-premises). The communication between the SL and WCF deployed on two geographically separate premises are connected using the Windows AppFabric Service bus.
The important point to note here is the SL application is not going to originate/reside in the same location as the WCF services (RHS on-premise). The SL application would have originated from different source, may be from a local web server on the LHS on-premise. So for the SL runtime the WCF services are from a different domain and cross-domain security policy file (clientaccesspolicy.xml/crossdomain.xml) is required to establish a connection.
Here comes the challenge, as explained in the basics topic earlier. The SL runtime is going to look for clientaccesspolicy.xml file on the root of the requested target domain. In the AppFabric Service bus case, the root is actually the Service bus namespace. Ex:
http://yournamespace.servicebus.windows.net , not the actual location of WCF services on the RHS on-premise. The SL runtime will try to make a HTTP request, equivalent of
And since that file is not available in that location, it will throw a security exception and won't allow any further network connection.
Previous hacky solutions:
So far developers tackled this challenge by creating a REST service on the WCF RHS on-premise covering the root URL, something as shown below.
public interface IClientAccessPolicy
[WebGet(UriTemplate = "clientaccesspolicy.xml")]
One of the challenges with this approach is you need to make sure you register the REST service at the end, after registering all your real WCF services. Since the REST service is at the root and it doesn't have a unique URI, registering it first will result in taking the complete namespace and trying to register any other services will result in an error saying
"The specified address already exists.Address....."
Developers tacked this scenario by either manually registering the REST (clientacccesspolicy.xml) service at the end, or by using some custom WCF behaviour logic to delay its registration process.
Hidden Gem in AppFabric SDK 2.0 CTP - Easy Solution
As part of the AppFabric SDK V2.0 CTP samples (download details provided at the end), Microsoft released a sample application called "ClientAccessPolicyPublisher", which allows you to upload your clientaccesspolicy.xml file to your root service bus namespace. Once the file is uploaded you can access it by simply navigating to it using the URL as shown below.
This completely eliminates all the challenges we have discussed so far and it makes AppFabric service bus easily accessible via Silverlight applications.
The tool is simple to use, open command prompt and execute the exe Microsoft.ServiceBus.Samples.ClientAccessPolicyPublisher.exe
After providing AppFabric Service bus shared secret credentials, it will show the options as shown above. "P" will upload the default clientaccesspolicy.xml file (found under the same folder), which is pretty generic and allows the entire http* and https* connections. If you got specific restrictions you can specify your own.
The other options are self explanatory, which allows to see the existing policy file and delete it if required.
Important: The sample project points to the "appfabriclabs.com" and its hardcoded in code, so you need to open program.cs file and find and replace all "appfabriclabs.com" with "windows.net".
var acsEndpoint = "https://" + serviceNamespace + "-sb.accesscontrol.windows.net/WRAPv0.9/";
\AppFabric SDK V2.0 CTP\Samples\ServiceBus\Silverlight\ClientAccessPolicyPublisher
Special thanks to Mikael Hakansson for pointing me to this SDK sample. When I was there in Stockholm, Sweden for the BizTalk user group meeting and biztalk360.com promotion, I was discussing this topic with Mikael, since it's in our road map to enable biztalk360 to use AppFabric service bus to support remote customer BizTalk server environment.