OK, back down from vacation – proud about the accomplishment and perhaps with some new perspectives. It really makes you think about the effects of the financial crisis if you happen to work primarily for banks… . Well.
Note: This is part of a series, you can find the related posts here…
The last post (pre-Kili ;-)) provided me with the necessary infrastructure to address the next topic: application security.
Silverlight is “secure by design”. It runs in a sandbox, only allowing restricted access to the local machine. Regarding server calls it supports HTTPS and windows authentication for intranets, it restricts URL access and allows only calls to servers explicitly opted in for. From a .NET perspective it has a changed programming model, no longer supporting CAS, but a more simple model that takes the restrictions into account that are already in place. It has the well-known interfaces IPrincipal and IIdentity in place, yet no implementation and no anchor to ask for them, like HttpContext.User in web applications.
Silverlight is so secure, it doesn’t even tell you, who you are.
From a purely technical perspective this is perfectly in order. The services I call are running on the server and it’s their job to make sure no one does something or gets to know something he isn’t entitled to.
On the other hand, many intranet applications need to know the user name, if only to display it. And they need the permissions granted to the user to hide buttons, menu entries or make edit fields read only – none of that for actual security reasons (the server would take care that the user couldn’t do any harm, anyway), but to improve the user experience, not letting him do things and telling him afterwards that he has had no permission to do what he did in the first place.
User and roles are available at the server at the ASP.NET runtime, and one “only” needs to make it available to the client. Matter of fact, ASP.NET provides the necessary service implementation readily available. This is also the way to integrate with ASP.NET forms authentication.
There are two caveats with this approach, though: These ASP.NET services provide roles and all, but they just don’t include the user name. Also, being services, I would have to call them asynchronously, which would incur at least a little time lag after starting the application, that I would have to deal with. A time lag that is unnecessary in intranet applications where the user is determined by windows authentication.
Thus my solution is as follows:
- On the server include the information about user name and his roles in the initparams, so that it is available for the SL application right form the start, without any lag.
- On the client pick up that information and mimic HttpContext.User to have a similar developer experience.
Of course, someone could fake this data, which might at first glance be a security flaw. But as I said, this information is only used to improve the user experience. Even if someone masqueraded as a different user, the sandbox on the client side still uses the actual user’s restrictions. And the same is true for the services that still have the responsibility to enforcing security anyway. I’m also not revealing sensitive information, since user name and permissions are not exactly protected data. And finally I could load the web page containing this data via HTTPS. Thus, form a security perspective I’m on the save side.
The server side is easy enough, since the necessary work has already been done. Step one is to include the information in the initparams within the ASP.NET page:
Step to is the respective implementation:
Mimic HttpContext.User? Well, there is no HttpContext, but we have the Application object which can be seen as a pendant of sorts. (I wouldn’t relate it to the HttpApplication, though, since an application in the ASP.NET sense spans all users.) Yet I’m reluctant to provide a base class to inject my pet feature, because that would bring me into conflict with any other library that may one day choose to do the same.
Luckily SL3 introduced the new concept of Application Extension Services (AES for short). AES have to implement a simple interface and are registered via the app.xaml. SL3 instantiates them and calls the StartService and StopService method to provide the hooks for initialization and shutdown. There will be another post about AES, thus I’ll leave it at that for now. Anyway, here’s the respective implementation:
It’s straight forward, it merely parses the information provided via the initparams. And the registration that will create the service at runtime is quite simple:
This is backed by boilerplate implementations of IPrincipal…
… and IIdentity:
From here I can use the user information at leisure, as I need it, and as I’m used to do. For example:
That’s all for now folks,