Authentication & Authorization in Silverlight

Introduction

In the previous article we saw a WCF Authentication and Authorization example using a Windows Client. In the distributed world we often end up with multiple consumers of the same service.  But the same client code won't be enough to run on the new client platforms, especially in Silverlight.

In this article we can explore using the same WCF service using a Silverlight client.

The core aspects we cover here are:

  •  Silverlight Client Creation

  • Cookie Container Usage

  •  Invoking Authentication Service

  •  Invoking Utility Service

Following are the activities involved:

Open the existing WCF service application

Create Silverlight application

Add Service References

Enable Cookie Container

Invoke Authentication Service

Invoke Utility Service

Run the Application

Create Service Client Factories

 

So now we can start with the above steps.

Step 1: Open the existing WCF service application

Open the previous WCF service application solution.

img1.gif

 

Step 2:  Create Silverlight application

Now add a new Silverlight Application into it and name it SilverlightClient.

img2.gif

Click Ok and in the next page use the same WCF application for hosing our Silverlight client.

The hosting in same WCF service discards the chance of Cross Domain policy error.

img3.gif

Please note that we are using Silverlight 4

Step 3:    Add Service References

Now we need to add references to the following services:

1)      Authentication Service (http://localhost:54332/AuthenticationService.svc)

2)      Utility Service (http://localhost:54332/UtilityService.svc)

img4.gif

 

Step 4:   Enable Cookie Container

Since Silverlight does not support Behavior Configuration, we need to use an alternative solution.  We can use Cookie Container which acts as the holder for cookie while communication with WCF services.

In the ServiceReferences.ClientConfigadd the tag enableHttpCookieContainer for both the services as shown below.

img5.gif

We are also adding a new class named Globals to store the CookieContainer globally.

namespace SilverlightClient
{
    public class Globals
    {
        public static CookieContainer CookieContainer
        {
            get;
            set;
        }
   }
|}

As in Silverlight an application needs only one authentication cookie to be stored in the client side.

Step 5:  Invoke Authentication Service

Now we can start by invoking the Authentication Service. The Service, on successful Login, returns the cookie in the message header.  This cookie will be stored in the Global Cookie Container.

Place a button on the main form and add the code in button click handler.

private void AuthenticateButton_Click(object sender, RoutedEventArgs e)
{
    bool httpResult = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
    Globals.CookieContainer = new CookieContainer();
    AuthSvc.AuthenticationServiceClient authClient = new AuthSvc.AuthenticationServiceClient();
    using (new OperationContextScope(authClient.InnerChannel))
    {
        HttpRequestMessageProperty property = new HttpRequestMessageProperty();
        OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = property;
        authClient.CookieContainer = Globals.CookieContainer;
        authClient.LoginCompleted += (object sender2, AuthSvc.LoginCompletedEventArgs e2) =>
            {
                if (e2.Result)
                    MessageBox.Show("Authentication Success!");
                else
                    MessageBox.Show("Authentication Failure!");
            };
 
        authClient.LoginAsync("tom", "chicago12", string.Empty, true);
    }
}

The Authentication Service was invoked after setting the cookie container to global cookie container.  This ensures the cookie will br stored globally.

 Step 6:   Invoke Utility Service

Now that we have the cookie inside Global.CookieContainer we can invoke the Utility Service by setting the cookie container property.

Place a new button and add the following code inside the click handler.

private void InvokeButton_Click(object sender, RoutedEventArgs e)
{
    Uri authUri = new Uri("http://localhost:54332/AuthenticationService.svc");
    Uri utilUri = new Uri("http://localhost:54332/UtilityService.svc");
    Globals.CookieContainer.SetCookies(utilUri, Globals.CookieContainer.GetCookieHeader(authUri));
    UtilSvc.UtilityServiceClient utilClient = new UtilSvc.UtilityServiceClient();
    utilClient.CookieContainer = Globals.CookieContainer;
    utilClient.GetDataCompleted += (object sender2, UtilSvc.GetDataCompletedEventArgs e2) =>
    {
        MessageBox.Show("Data: " + e2.Result);
    };
    utilClient.GetDataAsync(100);
}

Step 7:  Run the Application

Now you can run the application and use the buttons to play around with Authentication and Utility services.

img6.gif

Click on the first button to get Authenticated and you should get the following message:

img7.gif

Now click on the second button and you will get the data message as shown below:

img8.gif

If you are able to see the above message then the Authentication and Authorization is working fine with your Silverlight application.  Good Job!

Step 8: Create Service Client Factories

You have probably observed that the Utility Invocation is little tedious than the ordinary way.  We can make a lot of code to the background by using the ServiceClientFactory class.

img9.gif

The source code of the above class can be found in the attachment.  The Service Client Factory performs the following activities:

  1. Ensures on single instance of the class through Singleton design pattern

  2. Create properties for all services using Factory Method design pattern

  3. Performs the Authentication on first call

  4. Sets the Cookie Container for all Utility Service client instances

After having the service factory class the code for invoking Utility Service is simplified as below:

ServiceClientFactory.Insance.UtilityServiceClient.GetDataCompleted += (object sender2, UtilSvc.GetDataCompletedEventArgs e2) =>
    {
        MessageBox.Show(e2.Result.ToString());
    };
ServiceClientFactory.Insance.UtilityServiceClient.GetDataAsync(1000);

The application looks like below with the new features enabled.

  img10.gif

Summary

In this article we have seen how to use the WCF Authentication and Authorization from a Silverlight client application.