WPF Browser Hosted Applications (XBap) APTCA/Friend Assembly

Avalon browser hosted applications get trust based on the zone from which they deploy. This means Xbaps coming from Internet zone get Internet zone permission only and ones from Intranet zone get Intranet zone permissions etc…

These applications don’t have support for permission elevation where user can choose to give higher privileges than ones that application can get based on zone of deployment. There are three ways applications can demand more trust  that default permissionset allowed for the zone of deployment and demand can get satisfied.

  1. Deploy a custom CLR Security policy that modifies the default permissionset for the given zone
  2. Use a trusted publisher mechanism
  3. Use a fully trusted GAC‘ed assembly which allows partially trusted callers.

First way, is the most intrusive in terms of its impact. Only place it could be done is company intranet which is guaranteed to be secure. This means all the applications from anybody from that particular zone will get modified permission set. This can’t really work for Internet zone application because you would not deploy a custom CLR security policy on your machine that allows more trust to all the applications in the world.

Second way, is less intrusive than first one but it is still more open than the third one. By trusted publisher mechanism, you essentially say that all applications signed with that cert (which means all applications from particular publisher) can get permission set that they demand irrespective of their zone. This is still open check from end user’s perspective. because once this is granted anything from that publisher will run without a prompt. User needs to run full trust code (installer) on the machine to be able to do this.

Third way, can be less intrusive where installer runs to install a full trust assembly in the GAC which allows partially trusted callers. This in itself can be seen as worse than second option because GAC‘ed assembly that allows partially trusted caller means any code on Internet can call into that assembly. The security bar for this kind of assembly would/should be very high and it would mean you will need to think about not only bad used of your application calling that code but also *any* application calling that code. But you could lock down the code in this third way in such a way so that only your application and nobody else. It involves use of concept of Friend Assembly.  

For this to work three things need to happen…

  1. Assembly needs to be in the GAC to be found by Partially Trusted Code
  2. Assembly needs to to have AllowPartiallyTrustedCallers (assembly level) attribute so that it can be called by Partially Trusted Code
  3. Assembly needs to be marked InternalsVisibleTo (Assembly level) attribute so that it can be ONLY called by your Partially Trusted Code.

Doing first part, is pretty straightforward because on dev machine it can be done by GACUTIL or on user’s machine it can be done by installer.

Second part involves putting a assembly level attribute. You could put this in AssemblyInfo.cs that VS generates. It looks something like this…

//allows partially trusted caller
[assembly: System.Security.AllowPartiallyTrustedCallers]

Third part involves some more steps…

To use the InternalsVisibleTo in such a way that only your assembly can call into it, caller assembly needs to be strongly name signed. So lets say you will use FriendCaller.snk file that you can generate using sn.exe tool. You will use Public Key of that key to specific InternalsVisibleTo attribute. So it looks something like this…

//uses the strongname of the assembly to make internals visible
[assembly: InternalsVisibleTo(“FriendCaller,PublicKey=002400000480000094000000060200000024000
05253413100040000010001008b486e36a11b892dbe3c19af141bd9123c696
2ef7945fe10b1131e5bf6852d4a31ae192c21ad65ebe054fa94c6ac19c0c6ecd85
261ee2b0e7e4029aa8f569eddce5310c8731c8976405d19877c18163c6b0199
ffc4c617f8ab095b2b750dcf204e65bc000818ce36ce46e5c3f4d8a7ddfe6f9dfc3
99b65df1281a52a2ae5accc”)]

Note: I put line breaks to make it readable. In real code it would be one big line unless you have wrap set.

 First part of the attribute is pretty straight forward, it is the name of your assembly without the extension (.dll or .exe etc).

Here is how you generate second part…

  • sn -k FriendCaller.snk // Generate strong name key
  • sn -p FriendCaller.snk key.publickey // Extract public key from key.snk into key.publickey
  • sn -tp key.publickey > test.txt // dump the public key to text file instead of screen.
  • Copy paste in the public Key = part of the code above

Apart from these attributes the only code that I had in my sample FriendsCallee.dll is

using System;

namespace FriendCallee
{
        class MyPrivateClass
       {
                internal string PrivateFriendlyCall()
               {
                      return (“My friend is calling me”);
                }
        }
}

so all the classese and methods in my assembly are internal so nobody else could call into it from outside. As part of the post build process I added Gacutil command so that it gets added to GAC on my machine automatically. On users machine it would be installer doing it. Since you need to put this assembly in the GAC, it also needs to be strongly named signed but since it is irrelevant here, I am skipping that part.

Here is what I did to create an application…

  1. Create an XBAP from Visual Studio Template.(Assembly name FriendCaller.exe)
  2.  I will add reference to GAC’ed dll
  3. I will use the FriendCaller.snk to sign the assembly from Project/Properties Signing Tab.

Page1.xaml  of my applications looks like this…

<Page x:Class=”FriendCaller.Page1″
xmlns=”
http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
Title=”Page1″ Loaded=”OnPageLoaded”>
       <Grid>
               <TextBlock Name=”lblMessage”></TextBlock>
       </Grid>
</Page>

Page.xaml.cs looks like this…

namespace FriendCaller
{
          public partial class Page1 : System.Windows.Controls.Page
         {

                 public Page1()
                 {
                         InitializeComponent();
                  }

                 void OnPageLoaded(object sender, RoutedEventArgs e)
                  {
                            FriendCallee.MyPrivateClass mp = new FriendCallee.MyPrivateClass(); 
                            this.lblMessage.Text = mp.PrivateFriendlyCall();
                    }
          }
}

When you compile this application, I would have expected it to run and be able to call into a GAC’ed APTCA marked DLL even though I am calling internal method because FriendCaller.exe is friends with FriendsCallee.dll.

Unfortunately it did not work. CLR still threw security exception. For some reason, I needed to mark my application EXE (FriendCaller.exe) which was calling into that assembly also APTCA.

So when I added following code to AssemblyInfo.cs of my XBAP, it worked well as expected.

//allows partially trusted caller
[assembly: System.Security.AllowPartiallyTrustedCallers]

I have not yet figured out why I needed to add it or if there is better way to do this but once I do, I will post it.

Till then…you have a work around.

A Peace to End All Peace

I just started reading A Peace to End All Peace: The Fall of the Ottoman Empire and the Creation of the Modern Middle East. I have heard lot about this book so far. I have barely read Introudction but I am totally excited about reading this book. Title is based on a quote from Field Marshall Archibald Wavell that says

“After the ‘war to end war’ they seem to have been pretty successful in Paris at making a ‘Peace to end Peace.’ “

I found one good post with some perspective on Procrastination blog

RSS

I read this RSS releated post today on  Dead 2.0 blog. I must say this is one of my favorite technology blog. It was great to re-confirm how far away we (people who work in software) with people in real world who are supposed to use the tecnology. I loved the way Dead2.0 used term “Vanish” in context of RSS and his explaination. I remember reading one of the design books where books took power steering as one of the best designs because user never notices it working for it explicitly. RSS needs to be like that. I love RSS.

It is interesting from the perspective of usage pattern for the task. Before RSS, the only way I can read content is I have to visit individual sites. RSS solves the problems where I can read the feeds by getting updates etc but now user has to sacrifice the experiences that web site provide. I think what we need to do here so people get advantage of RSS without losing benefits of great experience.

 Here are few things I was thinking about ….

App Integration with RSS Reading experience

Today RSS feed reader has some standard UI that allows users to read it. But there is nothing content publisher can do to make that experience better.  We could solve this  Ability for RSS feed to say what their preferred reader is. This might be just a custom tag in RSS that specifies link to the reader. Link can point user to get richer application. User goes and installs the reader if they want it. 

Problem it solves…

  • User does not have to be stuck with what default UI and can get richer experience if they wanted

Problem it does not solve…

  • It is not integrated experience.
  •  User still has to go out of his way first time to get the reader. 
  • Different application can build different usage semantic and will be confusing for users. 

It would be great if there was an ability to RSS feed to specify the app they want to use for reading. That app gets executed when browser hits that RSS feed. This could also be done via Add-in model where browser provides the default viwer application and content provider provides addin that enhances that experience. This way browser can keep control over the usage sementic and keep it in the same ballpark. It means we only have platform for DATA part of the RSS but maybe we should have plugin based platform for RSS applications that closely integrated with browsers.

Got to figure out Way to Monetize RSS feeds.

I could think of 3 ways to let content publisher make money

Ads

  • Showing the ads RSS has as they are
  • Controlling the Ad experience in default RSS reader (special tag for Ads that get displayed on the side of the page etc)
  • We could also think of ways to get LIVE search ads in the news reader based on the content (This wont work for the people who make money off their own ads but might be interesting for free content)

Subscription (Authentication)

 There might be people who make money off of the subscription based content. That means they need to identify who the owner is no matter what the reading model is. This means we have to support authentication of this content and possibility obfuscation.

 Licensing: Viwer App having to licensed

I can see people actually making money off of partner deals such as Newyork times recommends “Foo” reader build by BAR company. They push people to use FOO through their  RSS and they 10% of every new license that comes because of nytimes feed. This might be weak.

Browse or Not to Browse

I read an interesting post today on Ryan Stewart’s blog about Apollo. According to Adobe Apollo is…

“The code name for a cross-operating system runtime being developed by Adobe that allows developers to leverage their existing web development skills (Flash, Flex, HTML, JavaScript, Ajax) to build and deploy Rich Internet Applications (RIAs) to the desktop.”

Here is what was interesting part for me

“The browser is a broken, but comfortable delivery medium for RIAs. People are familiar with the browser because that is how they have always interacted with the web. Ajax brought on the idea of web applications, and they work within a browser (after a number of hacks). Even the Flash Player runs within a browser, because that is how people access the web. But this is backwards. The kinds of things happening on the web now shouldn’t require a browser. Sure, we will still read blogs and search in a browser; but for the kinds of web apps we are seeing, using a browser is like trying to fit a square peg in a round hole – it won’t work well

Apollo (and technologies like WPF) take those applications and extract them from the browser. The power of the web is still there, but people are no longer going to have to interact with these applications inside a browser. There are going to be some difficult growing pains – people are going to resist at first. But change is good, and Apollo is an evolution of software development. We have seen the power of the web, but Apollo can make better use of that power by breaking the chains of the browser.”

I was not sure after reading this whether Apollo will only run outside browser but some presentation that I saw, showed a demo running Apollo based application in the browser.

Here are the things that I agree…

  1. I agree that Browser is comfortable delivery medium
  2. I agree the fact that though browser has been one way users have been interacting with web, it is changing with rise of applications that either hide the browser from end user (something like Media Center Applications) or they dont use browser at all such as rich connected client applications.

But here are things that I dont agree…

  1. I dont agree that Browser is broken for exact same reason Ryan mentions it. Browser is what people are familiar with. People dont have to “learn” application if it follows other things that they already see in the browsre. Things like navigation, back/forward etc. 
  2. Browser is also the way people are finding things out. This is the starting point. If you choose to do different things after clicking on a link then they will be starting new experience from end user perspective.

I think, the decision to stay in the browser or not should be left to app developer. App developer would make a if the UX they want is inside browser or not. I think in some case browser is still a great application host. For example, I dont mind my content application running in the browser. I would hate if I start my browser on CNN.com and then go to MSNBC.com to Samachar.com, each one of them opens a new windows. But I would not mind if it opens a new window if I am looking at CRM data etc. I am just picking the example that made sense to me but if you dont agree with those examples and have different examples then it still proves the point that app developer should be able to decide that app should run in the browser or not.

I definitly agree that we should not try to fit square peg in round hole but I hope we dont swing the pendulum in the other direction so hard that now different things are hader for user.

Apollo FAQ

Cookies and Avalon ClickOnce applications

ClickOnce supports command line parameters and this is one of the easiest way to get the command line parameters. There are lot of articles about how to pass command line/ URL parameters to ClickOnce application in general. Here is one of those articles. Needless to say that the same technique will work for Avalon Window based applications or Browser based applications (XBap).

To run Avalon applications, users will need to have .Net 3.0 runtime installed. For Vista, it is much easier because all the prerequisites are already there and X does not have to think about over head of getting user’s machine setup with runtime etc in most of the cases. The reason why I say most of the cases because there is possibility that Vista has been deployed and option component for .net 3.0 has been turned off. For detecting the presence of run time on user’s machine, .net 3.0 publishes its presence in user agent string as well as in mime type headers. Developer can use these to sniff the presence on user machine and direct user accordingly to either Microsoft website or to boostrapper setup package that can make sure the run time component are installed. VS has nice support for this kind of boostrapper where it also kicks of Installation of actual ClickOnce app at the end of the setup.

Since so many smart people have already talked about it, I wont get into more details here. I wanted to write something the customer specifically asked and we could/did not answer it off the top of our head so I thought it would be interesting to write it down for the posterity.

So here is the scenario…

Customer X is building a Avalon based full trust rich client. They want to deploy this client on all Avalon supported OSs and different languages. They want to download client language depending on the site through which user chose to install their application. For Example…if user navigates to German version of the site they want to install German version of the UI. They obviously take advantage of on demand download functionality that ClickOnce provides. For the cases where they don’t have to install Runtime before the application starts, it was all very simple because they can take advantage of URL parameter functionality mentioned about and pass the local to the application and then Application uses that information to set the culture and download the right culture specific UI DLL. But things get tricky when they have to direct user to boostrapper exe that installs runtime and then launches the ClickOnce installation. Now since the boostrapper.exe does not either accept or pass along these parameter, chain was broken. They want to know how the problem can be solved and here is the solution that I came up with.

  1. User hits domain1 to get to the page where the options are presented to him about downloads
  2. User chooses the option, since this domain knows its own locale, it will redirect user to Domain 2 for actual download and also passing in other options data along with local on URL parameter list
  3. Domain 2 parses URL parameters and servers up the page that actually contains the link for downloading setup.exe.
  4. This page also writes cookies that contain same information passed to domain2 from domain1
  5. When pages is served, cookies are written to disk and user clicks on setup.exe
  6. setup.exe finishes and launches ClickOnce installation
  7. ClickOnce installation finishes and then launches EXE
  8. EXE uses Application.GetCookie() API to read the cookies written.

PS: It is important the at you have domain that serves actual bits write the cookie if application that you are serving is supposed to run in Internet zone sandbox. In this condition reading cookie from some other domain would fail because you need webpermission to the domain you are trying to read cookies for. For full trust it is not a problem so theoretically for this case, domain  1 could have written the cookie and exe could have still read it.

Here some simple code snippets…

NOTE: Code is really just meant to prove point. I did not take any effort at all to do the right thing. I think Cookie reading can be improved a lot 🙂

Domain 1 Page that servers options

Options.aspx

<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”Options.aspx.cs” Inherits=”_Default” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”
http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title>Untitled Page</title>
</head>
<body>
<form id=”form1″ runat=”server” action=”
http://bombayboy1/asp/Download.aspx”>
<div>
<asp:CheckBox ID=”chkOptionalComponent” runat=”server” Text=”Download Optional Components” /><br />
Choose your Locale:
<asp:DropDownList ID=”drpdwnLocale” runat=”server”>
<asp:ListItem>English</asp:ListItem>
<asp:ListItem>German</asp:ListItem>
<asp:ListItem>Japanese</asp:ListItem>
</asp:DropDownList><br />
<br />
 <asp:Button ID=”btnSubmit” runat=”server” Text=”Submit (ASP)” OnClick=”btnSubmit_Click1″ /></div>
</form>
</body>
</html>

Options.aspx.cs

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click1(object sender, EventArgs e)
{
Response.Redirect(“Download.aspx?Locale=” + this.drpdwnLocale.Text + “&OptionalDownload=” + this.chkOptionalComponent.Checked);
}
}

Download.aspx

<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”Download.aspx.cs” Inherits=”Download” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>Untitled Page</title>
</head>
<body>
</body>
</html>

Download.aspx.cs

public partial class Download : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
NameValueCollection param = HttpUtility.ParseQueryString(this.ClientQueryString);
HttpCookie myCookie = new HttpCookie(“UserSettings”);
myCookie[“Locale”] = param[“Locale”];
myCookie[“OptionalDownload”] = param[“OptionalDownload”];
myCookie.Expires = DateTime.Now.AddHours(1);
Response.Cookies.Add(myCookie);
Response.Write(“<a href=\”
http://bombayboy1/Applications/CookieReader.application\”>Install </a> </br>”);
Response.Write(“<a href=\”
http://bombayboy1/Applications/Setup.exe\”>Install Runtime </a>”);
}
}

Application.xaml

<Application x:Class=”cookiereaderapp.App”
xmlns=”
http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
StartupUri=”Window1.xaml” Startup=”OnAppStartup”
>
<Application.Resources>
</Application.Resources>
</Application>

Application.xaml.cs

public partial class App : System.Windows.Application
{
public string Locale = null;
public string OptionalDownload = null;
public void OnAppStartup(object sender, StartupEventArgs e)
{
string cookie = Application.GetCookie(new Uri(“
http://bombayboy1″));
string[] split = cookie.Split(new char[] { ‘=’, ‘&’ });
if (split[1] == “Locale” && split[2] != string.Empty)
{
Locale = split[2];
}
if (split[3] == “OptionalDownload” && split[4] != string.Empty)
{
OptionalDownload = split[4];
}
}
}

Parenting by Luck

Today I came to work early in the morning, I got into elevator in the basement and pressed 2. When the door opened, I saw a kid about 6 years old standing right in the middle of the door. His sister (I presume) standing on one side of the door and his father (I presume) standing on the other side of the door. As Kid was looking up to me as I almost ran over him, I heard this father say “See I told you, you should stand in the middle, there might be people coming out!” I thought it was funny because it seemed like father was trying to make his point in vain by just logically arguing about it. My coming there at that exact point, made it just all easy for the father. It makes me wonder, how much of what Parent try to teach, depends on luck. There are millions of other factors that might affect the outcome of any advice given to them and everytime guy wont come out of elevator proving your point. Tough job!

Lincoln and Civil War

Still reading the Grand and Lee, and the book talks about the fact that what sourthern states were trying to do was within Constitutional limits of what what States can do at that point. This raised an imporatan question for me because though I agree with what Lincoln was fighting for, he apparantly overrode what constitution says. I wonder how civil war would have been handled in age of information/media today or if would have taken place at all. How do we know if the leader is doing the right thing or not by overriding the constitution in a democracy. It is easy to figure out, couple of centuries later but how do people make that decision in real time.

States were much more loosely bound together in the union but even in that case it was considered right thing to do to use military force to keep the states together. At that point, I would asusme popular vote in south would have gone in the direction of spliting from the union. I dont have any data yet but I am just making guess based on the fact that how ferociously the war was fought. In that case, if Lincoln was pollster like many politicians today, I wonder if he would have rached for wrong conclusion. Also from the perspective of India/Parkistan/Kashmir issue, I wonder how many analogies can be driven.