The “Silverlight Business Application” Project and NTLM
One very important detail that the classic “Silverlight Business Application” project has to teach us is how to use old-school NTLM authentication with Silverlight. This is a well-established but not very versatile/scalable way to authenticate users. In the real world of the corporate enterprise, NTLM is the only way to go. The assumption today is that there are authentication alternatives that Microsoft would encourage such as Microsoft Kerberos or maybe Active Directory Application Mode (ADAM). The leading constraint on these Authentication alternatives is what ASP.NET supports out of the box. The other leading constraint would be a requirement that authentication depends on Active Directory as is—no domain-level modification, no LDAP-level customizations—and no secondary set of users to authenticate outside of Active Directory (stored in a database).
One unexpected takeaway from these notes is the assertion that we cannot have NTLM authentication without setting up ‘default’ ASP.NET profiles. The defacto default ASP.NET profile is represented by AspNetSqlProfileProvider
. This implies that a SQL Server database is required to use NTLM—which seems very strange, encouraging us to look forward to finding out that the above assertion is incorrect.
Setting up NTLM Authentication
In conventional Silverlight App
constructor, state:
var webContext = new WebContext();
webContext.Authentication = new WindowsAuthentication();
this.ApplicationLifetimeObjects.Add(webContext);
In App.Startup
, state:
WebContext.Current.Authentication.LoadUser(
operation => Messenger.Default.Send(operation), null);
The MVVM Light Messenger expects this registration:
Messenger.Default.Register<LoadUserOperation>(this,
operation =>
{
if (operation.HasError) return; //TODO: handle LoadUser() error.
if (operation.User == null) return;
var user = WebContext.Current.Authentication.User;
this.CurrentUserName = user.Identity.GetWindowsUserName();
});
…where Identity.GetWindowsUserName()
is from a custom extension method.
In the system.web
node of web.config
, declare:
<authorization>
<deny users="?"/>
</authorization>
<authentication mode="Windows" />
<membership>
<providers>
<clear/>
</providers>
</membership>
<roleManager enabled="false">
<providers>
<clear/>
</providers>
</roleManager>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider"
type="System.Web.Profile.SqlProfileProvider"
connectionStringName="ApplicationServices"
applicationName="./" />
</providers>
</profile>
…where connectionStringName="ApplicationServices"
refers to:
<add name="ApplicationServices" connectionString="Data Source=MyDbServer;Initial Catalog=MyDb;User ID=MyUser;Password=my!pwd;MultipleActiveResultSets=true" />
…where the Data Source contains tables setup by the aspnet_regsql.exe
tool, covered in “Installing ASP.NET Membership services database in SQL Server Express 2008.” (An attempt to avoid doing all of this work with the AspNetSqlProfileProvider
, might lead one to use the System.Web.Security.WindowsTokenRoleProvider
, I found ne success here.)
Setting up WCF over NTLM
Visual studio will automatically generate ServiceReferences.ClientConfig
during the Add Service Reference… process. In the configuration\system.serviceModel
node of this document we might have this declaration:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
To support NTLM, declare:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="TransportCredentialOnly" />
</binding>
</basicHttpBinding>
</bindings>
Visual studio will automatically generate a system.serviceModel
node in web.config
, during the Add Service Reference… process. We must add a binding in system.serviceModel\bindings
to complement the one declared for the Client in ServiceReferences.ClientConfig
:
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
Setting up “Classic” NTLM Authentication on IIS 7.x
- Select Authentication from the Features View of Internet Information Services (IIS) Manager.
- Disable Anonymous Authentication (and all other forms of authentication).
- Enable Windows Authentication and select Providers… In the Providers dialog, move NTLM to the top of Enabled Providers.
Related Links
- “Walkthrough: Using the Silverlight Business Application Template”
- “Installing ASP.NET Membership services database in SQL Server Express 2008—Sukumar Raju’s Blog”
- “ASP.NET Forms Based Authentication with Active Directory”
- “RIA Services fallback from WindowsAuthentication to FormsAuthentication?”
- “Integrated Windows Authentication”
- “ASP.NET NTLM Authentication—is it worth it?”