Having recently released our initial offering of Silverlight controls, we are starting to get a feel for the sorts of issues Silverlight
developers commonly encounter in designing and developing their applications. One question which seems to pop up frequently is how
security and authentication should be handled in the context of a Silverlight application which interacts with WCF services. In applications
that include
Web.UI controls, especially those
with
SOA.UI integration, this question becomes even more important.
In this post, I will attempt to shine a bit of light on what we see as a typical approach to authentication and how it can be elegantly
integrated into a Silverlight 2 application and the WCF services it employs. We will use the example of simple ASP.NET forms authentication.
Step 1. Configure authentication for the application in its web.config file:
<system.web>
...
<authentication mode="Forms">
<forms name="secure">
<credentials passwordFormat="Clear">
<user name="milos" password="secret" />
</credentials>
</forms>
</authentication>
...
This is all we need to do to be able to rely on ASP.NET and its session cookies for authentication and session management. We do still need
to do a couple of things in order to connect our Silverlight and web service logic to this underlying mechanism.
Step 2. Write a simple WCF authentication service:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AuthenticationService
{
[OperationContract]
public bool Authenticate(string sUser, string sPass)
{
if (FormsAuthentication.Authenticate(sUser, sPass))
{
FormsAuthentication.SetAuthCookie(sUser, false);
return true;
}
return false;
}
[OperationContract]
public bool IsAuthenticated()
{
return HttpContext.Current.User.Identity.IsAuthenticated;
}
}
In this example, we implement two methods: one for checking whether the user is authenticated and another for authenticating her. We rely
entirely on built-in FormsAuthentication functionality.
With the AuthenticationService in place, we can plug it into our Silverlight application and its associated WCF services (including standard
SOA.UI services). For the former, we can create a service reference in the Silverlight application and use it in this sort of way:
Step 3. Implement authentication logic in the Silverlight application:
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
// When the page initializes, perform authentication if necessary:
AuthenticateAndInitialize();
}
void AuthenticateAndInitialize()
{
// Check whether the user is authenticated:
AuthenticationService.AuthenticationServiceClient oAuthClient =
new AuthenticationService.AuthenticationServiceClient(...);
oAuthClient.IsAuthenticatedCompleted +=
new EventHandler(oAuthClient_IsAuthenticatedCompleted);
oAuthClient.IsAuthenticatedAsync();
}
void oAuthClient_IsAuthenticatedCompleted(object sender,
AuthenticationService.IsAuthenticatedCompletedEventArgs e)
{
if (e.Result)
{
// The user is already authenticated, proceed with initializing the application:
InitializeApplication();
}
else
{
// Show login screen, get username and password (code not shown here), and authenticate:
Authenticate(sUsername, sPassword);
}
}
void Authenticate(string sUser, string sPass)
{
// Attempt to authenticate the given credentials:
AuthenticationService.AuthenticationServiceClient oAuthClient =
new AuthenticationService.AuthenticationServiceClient(...);
oAuthClient.AuthenticateCompleted +=
new EventHandler(oAuthClient_AuthenticateCompleted);
oAuthClient.AuthenticateAsync(sUser, sPass);
}
void oAuthClient_AuthenticateCompleted(object sender,
AuthenticationService.AuthenticateCompletedEventArgs e)
{
if (e.Result)
{
// The user is now authenticated, proceed with initializing the application:
InitializeApplication();
}
else
{
// Login failed, repeat the login screen procedure (code not shown here).
}
}
...
The (pseudo-)code above outlines the general approach to a simple login procedure which can be integrated into any Silverlight application.
We need to interface into this procedure from Silverlight because that is our client-side platform, but the authentication is actually
needed not for the client-side Silverlight operations, but for the server-side WCF layer. This brings us to the last step, and the real point
of the whole exercise: securing the service.
Step 4. Secure the service:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SoaFeedReaderDataGridService : SoaDataGridService
{
public override SoaDataGridSelectResponse Select(SoaDataGridSelectRequest request)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
// Implement service logic
...
The idea is to have the service check the user's credentials before proceeding to fetch data or perform other potentially sensitive
operations. In the example above, we are using a standard SOA.UI SoaDataGridService, but the same approach is used for any WCF service.
I hope this basic example clarifies things a bit when it comes to security and Silverlight+WCF applications. For more elaborate authentication
mechanisms, other options also exist, such as the ability to pass around custom data using SOA.UI APIs, but that is a topic for another day.
Cheers!