I’ve just published my first project on CodePlex, which is a WPF/MVVM tool based on the IDesign credentials manager, so it seemed an appropriate time to blog about using ASP.NET providers for authorisation while using Windows for authentication with WCF services. Admittedly this isn’t an original idea, in fact ScottGu blogged about it back in 2006, but for ASP.NET web applications instead. This is simply a variation on that.
Aside from the fact that SharePoint has done this since WSS 3.0/MOSS 2007, why would you want to do this? the main reason is because you may not have control over Active Directory (if you don’t regularly see any of the people who run the servers that you work on, then this is probably true of your situation) but you want to provide granular permissions on an application or service. Eventually you’ll want to delegate role management to an end-user so the product owners can be responsible for their own security. In my experience, the larger a company gets, the longer it takes to get a system access change request done – so this type of requirement is quite common. There are technical and business advantages to using Windows authentication (instead of the ASP.NET membership provider); such as being able to rely on the ambient security of your business domain for user authentication, but also that it removes the need for certificates in development or production. Often, network security administrators don’t like to create AD groups to meet the requirements of specific applications, so this is a “best of both worlds” solution that should keep everyone happy.
Implementation is done in the web.config. Basically it’s no different from using ASP.NET providers for everything (authentication and authorisation) except that you can miss out the authentication bits as all the main bindings default to Windows authentication. The only caveat is for the basicHttpBinding (which is insecure by default) where the security and transport client credentials have to be explicitly defined to use Windows authentication. The important bits are below:
<?xml version="1.0"?> <configuration> <connectionStrings> <!-- This is the connection string to the aspnetdb/credentials store database Update as appropriate --> <add name="AspNetDb" connectionString="Data Source=MyServerName;Initial Catalog=aspnetdb;Integrated Security=True;enlist=false" providerName="System.Data.SqlClient"/> </connectionStrings> <system.web> <!-- Replace the application name with the name of your application in the aspnetdb/credentials store database --> <roleManager enabled="true" defaultProvider="SqlRoleProvider"> <providers> <add name="SqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="AspNetDb" applicationName="MyApplication" /> </providers> </roleManager> </system.web> <system.serviceModel> <bindings> <basicHttpBinding> <binding> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" /> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior> <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
The client-side config for basicHttpBinding is:
<system.serviceModel> <bindings> <basicHttpBinding> <binding> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /> </security> </binding> </basicHttpBinding> </bindings> </system.serviceModel>