Using IIS Express to Secure Silverlight and WCF Applications
I’ve been using IIS Express lately with Silverlight and WCF services and have learned to appreciate the “real-world” advantage it gives you versus the built-in Visual Studio “Cassini” server. Although I’ve always preferred to use IIS whenever possible, sometimes that’s not an option when you’re first starting a project and working on a machine that doesn’t have IIS installed. By using IIS Express you can identify security, configuration and other issues that may occur as you move an application to a real IIS 7+ server upfront rather than finding out about the issues after you move an application to a dev/staging server. In this post I’ll walk-through some of the lessons learned and walls encountered when I started working with authentication in IIS Express. It’s easy to work with once you know a few fundamentals. If you don’t already have IIS Express installed (it comes with Visual Studio 2010 SP1) you can get it through the Web Platform Installer or here.
The details listed below should help get you started running Silverlight applications that consume WCF services on IIS Express. The general principles can be applied to other application frameworks such as ASP.NET though as well. Keep in mind that you’ll more than likely have to change additional configuration settings on your machine depending upon the type of security you’re using in your project.
Using IIS Express
Switching to IIS Express is a simple as right-clicking on your Web project and selecting Use IIS Express:
You’ll be prompted to create a new site to host your Web project:
After clicking Yes you’ll be presented with a message that says your website is ready to be hosted on IIS Express and you’ll be given the port number that will be used. If you’re switching an existing project to IIS Express you’ll want to make a note of the port number since it may be different than what Cassini was using. Any WCF service proxies you may have created will need to have their ServiceReferences.ClientConfig file updated to use the appropriate port.
Performing these steps adds configuration code similar to the following into the IIS Express config file:
<site name="SilverlightDemos.Web" id="3"> <application path="/" applicationPool="Clr4IntegratedAppPool"> <virtualDirectory path="/" physicalPath="[PathToYourProject]\MVVMWithSecurity\SilverlightDemos.Web" /> </application> <bindings> <binding protocol="http" bindingInformation="*:1660:localhost" /> </bindings> </site>
When you run your project it’ll now use IIS Express and a new icon will show in your tray. If you right click on the icon you can get into details about the hosted site:
Click Show All Applications to see additional details about your application. Notice that there’s a path listed for a configuration file named applicationhost.config. That file is useful for “tweaking” different features of IIS Express as you’ll see next.
Overriding IIS Express Security Default Settings
Now that you’ve seen how easy it is to enable IIS Express, let’s look at customizing it to handle security needs. If you have a Silverlight application that’s secured with Basic or Windows authentication then you’ll need to turn off anonymous access and allow other types of authentication to be configured. With IIS 7+ you can do that by adding the following into your Web project’s web.config file assuming overrides are allowed (note that I added the basicAuthentication element simply to show that you can configure that in web.config as well):
<system.webServer> <security> <authentication> <basicAuthentication enabled="false"/> <anonymousAuthentication enabled="false"/> <windowsAuthentication enabled="true" /> </authentication> </security> </system.webServer>
This code handles overriding the security defaults configured in IIS Express to enable Windows authentication. Here’s what the default configuration looks like for IIS Express:
<authentication> <anonymousAuthentication enabled="true" userName="" /> <basicAuthentication enabled="false" /> <clientCertificateMappingAuthentication enabled="false" /> <digestAuthentication enabled="false" /> <iisClientCertificateMappingAuthentication enabled="false"> </iisClientCertificateMappingAuthentication> <windowsAuthentication enabled="false"> <providers> <add value="Negotiate" /> <add value="NTLM" /> </providers> </windowsAuthentication> </authentication>
At this point you can right-click on a folder or file in your application (such as the file that hosts your Silverlight application) and set security by selecting Properties and then clicking the Security tab. This allows users and groups to be added or removed from the file or folder:
If you run your application with the web.config override configuration code in place to disable anonymous authentication and allow Windows authentication you’ll more than likely run into an issue. Out of the box, IIS Express doesn’t allow these items to be overridden. The configuration elements are locked down in the IIS Express configuration file named applicationhost.config.
Note: If you’re calling a WCF service from a Silverlight application you won’t see the error page of course. I used Fiddler to view the error and display it. After starting Fiddler and then running your application you can click the URL in error on the left side of Fiddler and select the WebView tab in the response area (bottom right) as shown next:
To fix this error, open your applicationhost.config file by going to Documents\IISExpress\config\applicationhost.config. Search for anonymousAuthentication in your file editor and you’ll find the following section toward the top of the config file:
<sectionGroup name="authentication"> <section name="anonymousAuthentication" overrideModeDefault="Deny" /> <section name="basicAuthentication" overrideModeDefault="Deny" /> <section name="clientCertificateMappingAuthentication" overrideModeDefault="Deny" /> <section name="digestAuthentication" overrideModeDefault="Deny" /> <section name="iisClientCertificateMappingAuthentication" overrideModeDefault="Deny" /> <section name="windowsAuthentication" overrideModeDefault="Deny" /> </sectionGroup>
Set the overrideModeDefault attribute to a value of Allow for anonymousAuthentication and windowsAuthentication (and any others you want to override in web.config).
Working with Security in Silverlight Applications and WCF Services
If you’re using Windows authentication in your Silverlight application and also using WCF services to send and receive data then you’ll need to configure the services. With Windows authentication already enabled in the project (due to the system.webServer tags added earlier that overrides the defaults) you’d think that you could simply run the project and be ready to go. Not so fast! If you look in your web.config file where the WCF services are hosted you’ll find config elements similar to the following for Silverlight-enabled WCF Services:
<bindings> <customBinding> <binding name="customBinding"> <binaryMessageEncoding /> <httpTransport /> </binding> </customBinding> </bindings>
If you’re only using Cassini (built-in Visual Studio server) and enabled NTLM authentication then you can add the following on the httpTransport element:
<httpTransport authenticationScheme="Ntlm" />
However, you may need to change that when using IIS Express. I had to change Ntlm to Negotiate and then things worked…for the most part. You may still see another error that I’ll discuss next.
<httpTransport authenticationScheme="Negotiate" />
Handling MEX End Points
If you run your application at this point IIS Express will start and the Silverlight application will appear (you may have to login depending on how your browser handles security credentials). However, you may see yet another error which can be puzzling given that you’ve told IIS Express to allow security configuration overrides and configured the appropriate WCF bindings to support the authentication scheme. I fought the error that occurred for a bit and finally realized that my MEX endpoint needed to be commented out in order for things to work properly. Locate your WCF services element in the web.config file where your WCF service(s) are hosted and comment out the MEX endpoint:
<service behaviorConfiguration="SilverlightDemos.Web.Services.PeopleServiceBehavior" name="SilverlightDemos.Web.Services.PeopleService"> <endpoint address="" binding="customBinding" bindingConfiguration="customBinding" contract="SilverlightDemos.Web.Services.PeopleService" /> <!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />--> </service>
At this point you should be able to run the application. However, it’d be nice to use the MEX endpoint even with Windows authentication. To get that going add the following code into your web.config file within the bindings element:
<basicHttpBinding> <binding name="MEXBinding"> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" /> </security> </binding> </basicHttpBinding>
Now change your MEX endpoint to the following so that it uses the custom basicHttpBinding:
<endpoint address="mex" binding="basicHttpBinding" contract="IMetadataExchange" bindingConfiguration="MEXBinding" />
Your MEX endpoint should now work since it’s configured to use Windows authentication. At this point you should be on your way using IIS Express and Windows authentication with a Silverlight application that consumes a WCF service.
Conclusion
IIS Express provides a way to develop and test code in a more “real-world” environment compared to using Visual Studio’s built-in web server. By using IIS Express you can setup your project configuration code to use different types of security plus work with other features exposed by IIS 7+ right on your development machine.I highly recommend it if you want to identify configuration, security as well as other issues early in the development process that may occur when moving an application from a local development machine to IIS 7+.
As mentioned at the beginning of this post, you’ll probably have to change additional configuration sections depending upon what type of security you’re using. I hope this helps point you in the right direction though.