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:

  1. Create Silverlight Project
    create_silverlight_project_from_template
  2. Choose to have the Visual Studio create a web site to host the Silverlight application
    select_web_site_for_silverlight_app
  3. Select the created web site and add Silverlight enabled WCF service to it.
    add_silverlight_enabled_wcf_web_service
  4. Open web site project properties and on Web tab, select Create Virtual Directory
    create_virtual_directory_for_web_site
  5. 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
    disable_anonymous_access
  6. Open ASP.NET tab and edit Authorization configuration – Deny access for anonymous users for all requests
    deny_anonymous_users_in_asp_net
  7. Restart IIS  - sorry, no picture here :)
  8. 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;
    		}
    	}
    }
    
  9. 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>
  10. Make sure that project builds and try to open DemoService.svc in browser
    browse_to_test_web_service
  11. 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.
    add_service_reference_to_silverlight_app
    use the Discover button to use the service in our solution
    add_service_reference_to_silverlight_app_2
  12. 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
    
  13. Build and run the application.
  14. 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.
    could_not_download_the_silverlight_application
  15. 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.
    add_mime_type_to_iss
  16. 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.
    cross-domain_policy_is_missing
    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>
    
  17. Place the XML file in to web server root folder and start the client application again.
  18. Now the application should start and you should be able to see the cute minimalistic design of our client app.
    client_app_ready_to_roll
  19. Press the Query Service button and wait for breakpoint to trigger (here I assume you have set it up in advance)
    debugger_quickwatch_of_webservice_method
  20. Well done, we have working client consuming WCF web service using Windows Integrated Authentication!
    result_of_web_service_call

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.
allow_authenticated_users_to_access_folder_in_my_documents

Please leave feedback! Thank you.

This entry was posted in Silverlight, WPF and tagged , , , , . Bookmark the permalink.
  • Shoeb

    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

  • Andy McMullan

    Thanks very much – I was *finally* able to get integrated authentication working after going through your steps.

  • http://rouslan.com Rouslan Grabar

    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.

  • Tobby

    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.

  • lamynes

    I am not able to reference my service form the MainPage.cs file.

  • Paul

    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;
    }

    }
    }

  • Xiang

    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.

  • david

    Same question as Xiang… is there a way to avoid having it prompt the user for their login/password each time?

  • Siddharth

    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

  • Max

    We spent 3 man days days trying to figure out the solution before we found this site. It solved the problem.

    Thanks a lot.

  • Sanjeev

    Thank you….. gr8 help by you.

  • Olly

    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.)

  • Olly

    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}

  • Deva

    Thanks. really useful. keep rocking!!!

  • http://- jordy

    i’m still getting the windows prompt to ask me for username/password, any help?

  • Rajesh P.N.

    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.

  • john

    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!

  • http://tuts9.com/questions/8657/iis6-configuration-for-wcfsilverlight IIS6 configuration for WCF/Silverlight | The Largest Forum Archive

    [...] the simple senario of running a WCF service to return Active directory information on a user. (http://rouslan.com/2009/03/20-steps-to-get-together-windows-authentication-silverlight-and-wcf-servi...) using Silverlight 4 & .net [...]

  • Hariom

    We have followed all steps given above but still windows
    authentication is not working. any help regarding this will be
    appreciated.

  • Gaurav

    Hi,

    This is really a helpful post. But it works fine only when silverlight application and WCF service are on the same machine.

    Everytime, it asks for user name and password when client and wcf are on two different machines.

    Any idea about suppressing User name/password dialog, so that it always impersonated the logged on user.

    Regards,
    Gaurav

  • Madhu

    I am stuck with same problem. On hosted environment getting the login/password prompt. Doesn’t happen on dev machine. Did anyone find solution for this?

  • Rupert

    Just what I needed, thanks! Minor point is that if you happen to have a “mex” binding enabled (my project did) remove it. Then it all works.

  • Adluri

    It is working fine but Every time it asks prompts for user credentials wcf call a wcf functions

    Any idea about suppressing user credentials prompt dialog.

    Regards,
    Shiva

  • Paras Sharma

    Mice explaination, it is working..

  • Harry

    Having the same problems as most of the others: still prompts for username and password.

  • http://profiles.google.com/vasiliev.maxim Maxim Vasiliev

    Hi! How to get it work with Moonlight Client?

  • Arglwargl

    Awesome, worked out of the box! 

    We adapted the tutorial for use with Kerberos & impersonation/delegation. Also, we make use of https connections, since tokens are not encrypted within the message body!

    Cheers!

  • Debasish Das

    Hi Rouslan,
    I gone through your steps, same i am getting access policy exception, I kept  clientaccesspolicy.xml in root folder even though no luck, I tried to use fiddler to make sure http://your_host_name_here/clientaccesspolicy.xml is serving 404 error, but i didn’t found any request like http://your_host_name_here/clientaccesspolicy.xml in the left pannel of fiddler. where exactly I am wrong?Please help me out.

    Regards 
    Debasish