My Blog On .NET

and other ramblings by Jeremy Brown
posts - 20, comments - 6, trackbacks - 16

Creating a custom Principal and Identity for Silverlight 2

I've been spending some time exploring Silverlight 2 and having a great time doing so. The more I work with it the more I realize its potential at being a game changer for creating Internet applications. The focus I have had is not so much on the rich eye popping user experience it can create, but more on how to build real world business applications. So after getting my head around using web services within Silverlight I began to explore role-based security. I came across an excelling blog post by Brad Abrams entitled "Accessing the ASP.NET Authentication, Profile and Role Service in Silverlight". It is a great example on how to use WCF to authenticate a user within a Silverlight application using the ASP.NET application services. However with Silverlight truly being a client-side application and not a stateless web page I wanted to see if there was support for a Principal and Identity objects much like we having in Windows and ASP.NET. What I found is that there are no classes implemented within the CLR used by Silverlight not even the GenericPrincipal and GenericIdentity but the interfaces IPrincipal and IIdentity are there to create our own.

To see how I did this you can download the source code here.

In the SilverlightPrincipalDemo project I added two classes called SilverlightPrincipal and SilverlightIdentity that each implement IPrincipal and IIdentity respectively. The SilverlightPrincipal class like other principal classes under the .NET framework will represent the identity and the roles of a user. These classes will also encapsulate the service calls to authenticate a user and retrieve the roles the user belongs to. Since Silverlight will only allow asynchronous service calls these classes  also expose events that are used by the application to know when a authentication request has completed. This is also the reason why there is no constructor creating and authenticating a user. Instead the default constructor for SilverlightPrincipal will simply create an anonymous unauthenticated user with no roles assigned. To authenticate a user I added a Validate method to the SilverlightPrincipal class that will call the internal Validate method on the SilverlightIdentity class which will invoke the service call to authenticate the user. SilverlightPrincipal also subscribes to a custom event on the SilverlightIdentity class to be notified when the authentication request is completed. If the user is authenticated the SilverlightPrincipal class will then invoke a service call to retrieve the roles for the user. When the role service call is complete it will fire an event to notify the caller of the Validate method that the request is complete. This event is also fired if the user failed authentication.

Once these classes were created I exposed a read-only property of type SilverlightPrincipal in the App class called CurrentPrincipal so that the principal would be available globally. In the Page class I also created a CurrentPrincipal property that references the principal object in the App class. This was more for convenience. Here is the property in the page class.

   1:  /// <summary>
   2:  /// Provides a shortcut to the current application principal.
   3:  /// </summary>
   4:  public SilverlightPrincipal CurrentPrincipal
   5:  {
   6:      get { return (Application.Current as App).CurrentPrincipal; }
   7:  }
 

Here is a sample on using the SilverlightPrincipal class to authenticate a user.

   1:  //Set up Principal Event Handlers
   2:  CurrentPrincipal.PrincipalValidationRequestCompleted += CurrentPrincipal_PrincipalValidationRequestCompleted;
   3:   
   4:  //Authenticate User
   5:  CurrentPrincipal.Validate(userName, password);

When the event handler is called it can then update the UI based on the current principal. Here is an example.

   1:  // Enables/Disables buttons based on the current application principal.
   2:  LogInManager.IsEnabled = !CurrentPrincipal.Identity.IsAuthenticated;
   3:  LogInEmployee.IsEnabled = !CurrentPrincipal.Identity.IsAuthenticated;
   4:  LogOut.IsEnabled = CurrentPrincipal.Identity.IsAuthenticated;
   5:   
   6:  ManagerOnlyTask.IsEnabled = CurrentPrincipal.IsInRole("Management");
   7:  EmployeeOnlyTask.IsEnabled = CurrentPrincipal.IsInRole("Employee");

There is also a corresponding LogOut method in the SilverlightPrincipal class that will invoke a log out service call and then reset the identity back to an anonymous unauthenticated identity with no roles assigned. It also has an event that can be subscribed to so the UI can be updated.

Print | posted on Thursday, May 22, 2008 7:21 AM |

Feedback

Gravatar

# re: Creating a custom Principal and Identity for Silverlight 2

This is great code, and I've been able to quickly and easily implement it in my Silverlight projects. However, I'm trying to figure out the best way to go about enabling/disabling some buttons based on the roles the current user is a part of. It would be nice to be able to bind to a property in the page that references the CurrentPrincipal and check to see if the user is authenticated and is in role xxx. Is this a good approach? Or is it better to manage the enabling/disabling in the code rather than the Xaml? If this sounds like a good approach, would you consider doing a supplimental blog post showing us how we might go about the binding?
8/1/2008 9:54 AM | Chris Swain

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 1 and 3 and type the answer here:

Powered by: