Posted on March 12, 2009 - by Rouslan Grabar
20 steps to get together Windows Authentication, Silverlight and WCF service
For one of my projects I had to query WCF web service for some data and display it in the Silverlight powered client. The web service should return data relevant to the identity of the person, querying the service with the Silverlight client. The choice of Silverlight over other technologies has been made to meet requirements for rich interface, consisting of the flexible grid with grouping, sorting and filtering. Pretty much the same grid as the one you may be looking at every day while using Microsoft Outlook. Since the application should be used inside the corporate intranet, one of the requirements was the usage of integrated Windows authentication,
I started experimenting with WCF service project template in Visual Studio. The only method of the new web service was supposed to return login name of the current user, but ServiceSecurityContext.Current.WindowsIdentity.Name was not available at all (the context was null).
Googling for the solution brought advices about using the ASP.NET services with Form Authentication, which effectively renders usage of the Active Directory useless.
To make long story short here are the steps:
- Create Silverlight Project

- Choose to have the Visual Studio create a web site to host the Silverlight application

- Select the created web site and add Silverlight enabled WCF service to it.

- Open web site project properties and on Web tab, select Create Virtual Directory

- Start IIS management console and edit newly created directory’s security settings. You have to disable anonymous access and make sure you have Windows authentication selected

- Open ASP.NET tab and edit Authorization configuration – Deny access for anonymous users for all requests

- Restart IIS - sorry, no picture here :)
- Now time to implement DemoService.svc
using System.ServiceModel; using System.ServiceModel.Activation; namespace RouslanComDemoApp.Web { [ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class DemoService { [OperationContract] public string GetWindowsUsername() { return ServiceSecurityContext.Current.WindowsIdentity.Name; } } } - Open Web.config and locate section <system.ServiceModel>. Replace the entire section with the following directives:
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="winAuthBasicHttpBinding"> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows"/> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="RouslanComDemoApp.Web.DemoServiceBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> <services> <service behaviorConfiguration="RouslanComDemoApp.Web.DemoServiceBehavior" name="RouslanComDemoApp.Web.DemoService"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="winAuthBasicHttpBinding" contract="RouslanComDemoApp.Web.DemoService" /> </service> </services> </system.serviceModel>
- Make sure that project builds and try to open DemoService.svc in browser

- Now we can get back to the Silverlight client app, that should consume the service we have just created. So lets add the service reference to the Silverlight project.

use the Discover button to use the service in our solution

- Now open Page.xaml and replace the contents with the code snippet below
using System.Windows; using RouslanComDemoApp.DemoServiceReference; namespace RouslanComDemoApp { public partial class Page { public Page() { InitializeComponent(); } private void QueryServiceButton_Click(object sender, RoutedEventArgs e) { DemoServiceClient ws = new DemoServiceClient(); ws.GetWindowsUsernameCompleted += ws_GetWindowsUsernameCompleted; ws.GetWindowsUsernameAsync(); } void ws_GetWindowsUsernameCompleted(object sender, GetWindowsUsernameCompletedEventArgs e) { UserNamePlaceHolder.Text = e.Result; } } } //please note, the code above does not use error checking for clarity - Build and run the application.
- You should now get nothing but the empty blank IE screen with little yellow warning sign in bottom left corner, which is there to say, that the Silverlight could not be loaded.

- To fix this problem you have to tell IIS about Silverlight mime type. It does not know that files with .xap extension should be served with application/x-silverlight-app content type header.

- Now if you run the application once again, you will be presented with one more obstacle. This time friendly and informative Visual Studio exception window tells you something about missing access policy.

So let’s have one in place. Create file clientaccesspolicy.xml and put in there the following XML. Please note this is a sample policy and should not be used as is in production environment!<?xml version="1.0" encoding="utf-8" ?> <access-policy> <cross-domain-access> <policy> <allow-from> <domain uri="*"/> </allow-from> <grant-to> <resource include-subpaths="true" path="/"/> </grant-to> </policy> </cross-domain-access> </access-policy>
- Place the XML file in to web server root folder and start the client application again.
- Now the application should start and you should be able to see the cute minimalistic design of our client app.

- Press the Query Service button and wait for breakpoint to trigger (here I assume you have set it up in advance)

- Well done, we have working client consuming WCF web service using Windows Integrated Authentication!

PS: In case you happen to host your web service in a web site located inside your “My Documents” folder, then you should update NTFS permissions for web site folder so authenticated users could access it.

18 Comments
We'd love to hear yours!
Leave a Reply
Here's your chance to speak.


Visit My Website
May 11, 2009
Permalink
Shoeb said:
Hi Rouslan,
I followed the steps for 3 times, still I am not going through. It throws Communication Exception when service method is called.
Am I missing anything. I need to sort this out asap.
Regards,
Shoeb
Visit My Website
May 12, 2009
Permalink
Andy McMullan said:
Thanks very much – I was *finally* able to get integrated authentication working after going through your steps.
Visit My Website
May 12, 2009
Permalink
Rouslan Grabar said:
Shoeb, can you please post the bits from the actual exception from the web service call? You also might want to ensure that the clientaccess policy file is accessible. To do that you may use fiddler tool (http://www.fiddler2.com). With help of this tool you will be able to confirm that request for http://your_host_name_here/clientaccesspolicy.xml is not served as a 404 error.
Visit My Website
May 23, 2009
Permalink
Tobby said:
You rock!! I’ve been looking for a solution to use Windows Auth with Silverlight and your example helped me get my app integrated in an hour. Thanks.
Visit My Website
September 10, 2009
Permalink
lamynes said:
I am not able to reference my service form the MainPage.cs file.
Visit My Website
September 11, 2009
Permalink
Paul said:
I keep getting the error
:Error 1 The type or namespace name ‘GetWindowsUsernameCompletedEventArgs’ could not be found (are you missing a using directive or an assembly reference?)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ADAuthenticate.Web.ADServiceReference;
namespace ADAuthenticate
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
void QueryServiceButton_Click(object sender, EventArgs e)
{
ADClient ws = new ADClient();
ws.GetWindowsUsernameCompleted += ws_GetWindowsUsernameCompleted;
ws.GetWindowsUsernameAsync();
}
void ws_GetWindowsUsernameCompleted(object sender, GetWindowsUsernameCompletedEventArgs e)
{
UserNamePlaceHolder.Text = e.Result;
}
}
}
Visit My Website
October 27, 2009
Permalink
Xiang said:
I still get the Login/Password prompt window everythime I make a call to the WCF service.
Also, I could not make it work in sharepoint 2007.
Visit My Website
October 31, 2009
Permalink
david said:
Same question as Xiang… is there a way to avoid having it prompt the user for their login/password each time?
Visit My Website
November 10, 2009
Permalink
Siddharth said:
Hi,
Even after adding the MIME Types (.xap/.xaml/.xbap) i still get the error 2104 in step 15. Any ideas how to go about it.
I am using .net 3.5 with Silverlight 3 and WCF enabled service in it.
Thanks,
Siddharth
Visit My Website
November 13, 2009
Permalink
Max said:
We spent 3 man days days trying to figure out the solution before we found this site. It solved the problem.
Thanks a lot.
Visit My Website
December 16, 2009
Permalink
Sanjeev said:
Thank you….. gr8 help by you.
Visit My Website
December 30, 2009
Permalink
Olly said:
Excellent! Wish I’d found this earlier.
Hope the following is useful to someone…
I use binary message encoding to make things a little faster. My element looks like this:
I also had problems because we use urls on our intranet in the form http://servername/etc/etc while the service reference generated by VS uses an alias, eg. http://servername.domain.blah.blah/etc/etc. IE doesn’t recognise this alias as being on our Intranet, so challenges the user with a password request screen.
This was easily fixed by modifying the ServiceReferences.ClientConfig file and replacing the longer alias with the short form. IE then recognises this as being on the Intranet and silently passes the credentials.
You can control whether or not IE does this from (IE 7/8) Tools | Internet Options | Security | Custom Level then locating User Authentication and selecting “Automatic logon only in Intranet zone” or “Automatic logon with current user name and password”. (The latter would be dangerous.)
Visit My Website
December 30, 2009
Permalink
Olly said:
Oops! In my above comment the xml sections have been removed. I’ll insert them again using {} instead…
My {bindings} section in web.config looks like this:
{bindings}
{customBinding}
{binding name=”customBinding0″}
{binaryMessageEncoding /}
{httpTransport authenticationScheme=”Negotiate” /}
{/binding}
{/customBinding}
{/bindings}
Visit My Website
March 17, 2010
Permalink
Deva said:
Thanks. really useful. keep rocking!!!
Visit My Website
April 21, 2010
Permalink
jordy said:
i’m still getting the windows prompt to ask me for username/password, any help?
Visit My Website
April 24, 2010
Permalink
Rajesh P.N. said:
I followed the steps, It was working fine with localhost. When I access it through other system with IP address, it prompts for the username/password.
Please let me know how to avoid the same, and to use the client identity.
Visit My Website
May 13, 2010
Permalink
john said:
I can view the page from Visual Studio, but when not if I run it from the folder or try to access from a different computer. Do you know what could be my issue?
FYI, I am getting “Error on page” in IE: Message: Unhandled Error in Silverlight Application [Async_ExceptionOccurred]
Arguments:
Debugging resource strings are unavailable.
Thanks!