With ASMX web services, a popular way to secure the service within an intranet scenario such that it authenticates and authorizes callers is to configure the cient with a fixed identity. The fixed identity would then flow to the service and the service would authenticate using Windows authentication. Within the service, you can then authorize the caller in the web.config and/or using PrincipalPermissions and Principal.IsInRole checks.
This is an elegantly simply approach for doing the right thing from a security perspective, so how is this accomplished in WCF?
In Juval Lowy's excellent book "Programming WCF Services", he asserts, and I agree that security is one of the most granular and complex aspects of WCF. There are several reasons for this, but primarily I believe it is due to the fact that various aspects and scenarios can be addressed that either fell beyond the reach of traditional ASMX services (WSE not withstanding) as well as the fact that there really isn't a least common denominator when it comes to transport. This means that a service can be deployed to an IIS environment for invocation strictly over HTTP/HTTPS or as a WAS or self-hosted application using TCPIP or MSMQ.
Although your searches on Google and the MSDN groups may not prove fruitful, it turns out it is quite simple to implement the basicHttpBinding with Windows Authentication, or, more academically known as the trusted subsystem model. Be warned that MSDN and othe resources regard the basicHttpBinding as a red-headed-step-child and this is obvious by the sheer lack of attention this still very relevant configuration gets in various literature. How soon we forget that just a year or so ago, unless you rolled WSE, you were doing the equivelent of basicHttpBinding!
Don't get me wrong, if your deployment scenario allows for it, I strongly encourage you to explore the more robust bindings, but if you are supporting non-WCF clients in an intranet IIS scenario, then this recipe is for you.
In the web.config for the service:
1. Set the SecurityMode to TransportCredentialsOnly:
<bindings>
<basicHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
2. In the Transport element, set the ClientCredentialType to Windows:
<bindings>
<basicHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
3. The Bindings element should resemble the following:
<bindings>
<basicHttpBinding>
<binding name="MyBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
4. Be sure to set the BindingConfiguration for each Endpoint in the Service element to the name of the BindingConfiguration.
5. I'm getting lazy, so I won't go into PrincipalPermission code in this initial version. I'll instead demonstrate the brute force apporach which if nothing else will ensure that not just any client can call your service. Add the allow/deny elements to the Authorization element in the system.web element section:
<system.web>
<authentication mode="Windows"/>
<authorization>
<allow roles=".\Developers"/>
<allow users="DOMAIN\ServiceAccount"/>
<deny users="*"/>
</authorization>
</system.web>
6. Naturally, these bidnings need to jive with IIS. What this essentially means is that the virtual application hosting your WCF service will need to be configured to use Windows Integrated authentication. Be sure to remove Anonymous Access.
On the client side, svcutil will generate the corresponding client elements to match that of the service. The assumption here, of course is that if the client is an ASP.NET application, it must be configured to run as a fixed identity. This is accomplished by changing the processModel element in the machine.config (IIS 5) or creating an application pool and assigning a fixed identity (not NETWORK SERVICE). If using a Windows client, the credentials of the actual user will be passed downstream.
As I get more time, I'll update this recipe with more detail, including the role-based Principal code so that the operations/methods themselves can be secured at a more granular level. For now, this should get most of you on the right track and hopefully save you some time.