I have a question around WCF authorization against a domain account over HTTP traffic hosted on IIS (none production so no ssl cert was available to use over the internet)
I'd like to know how to set up windows authentication from a client to my web service. currently I'm testing on the same LAN so proxies are not a problem
I have included a list of tried steps at the end of this post
Edit: The error that is occurring is just Access is denied, nothing else, given from the
try, catch in the Client Application. If there is a way to get more detailed information, please let me know and ill add the result to the post.
WCF Service code:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single, IncludeExceptionDetailInFaults = true)]
public class Data : IData
{
[PrincipalPermission(SecurityAction.Demand, Role=#"Administrators")]
public List<Incident> GetCases()
{
Queries query = new Queries();
List<Incident> iList = query.CallCases();
return iList;
}
}
WCF Web Config Bindings:
<wsHttpBinding>
<binding name="TransportSecurity">
<security mode="None">
<message clientCredentialType="Windows" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
WCF Web Config Behavior:
<behavior name="Behaviour1">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="true" />
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="http" port="9577" /> ///This port is correct
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
WCF Web Config Service:
<service behaviorConfiguration="Behaviour1" name="WebService1.Data">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="TransportSecurity" contract="WebService1.IData">
<identity>
<dns value="demo.DomainName.co.uk" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
Client Application (Has Service reference added)
DataClient client = new DataClient();
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
PrincipalPermission principalPerm = new PrincipalPermission(null, "Administrators");
principalPerm.Demand();
Console.WriteLine("Demand succeeded.");
client.ClientCredentials.Windows.ClientCredential.Domain = "Domain Name";
client.ClientCredentials.Windows.ClientCredential.UserName = "User Account";
client.ClientCredentials.Windows.ClientCredential.Password = "Password";
//client.ClientCredentials.UserName.UserName = #"UserAccount#domain.com";
//client.ClientCredentials.UserName.Password = "Password";
//client.ClientCredentials.UseIdentityConfiguration = true;
try
{
List<Incident> cases = client.GetCases().ToList();
foreach (Incident Inc in cases)
{
Console.WriteLine(Inc.CaseID);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Attempted Resolutions:
Using Domain and Local Users
Modifying the Client Credential type to basic, NTLM and Windows
using setting IIS to use
IIS has Basic and Windows Authentication Enabled
if you need any more information please don't hesitate to ask.
Thanks for any help you can provide
#Tim pointed me in the right direction, this was the resolution:
<wsHttpBinding>
<binding name="TransportSecurity">
<security mode="Message">
<message clientCredentialType="Windows" algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
Because I have no SSL Certificate I needed to set the security mode to Message, I was getting confused as most people test using SSL, which would require transport security as well I had set it to None for testing.
Thanks for the help Tim
Related
I have a Net Framework 4.5 WCF Service, running with async/task methods. It is deployed on a valid URL, with a correct Digicert certificate, assuring the domain. We have a "client certificate", with a "one-to-one" mapping, and all its ok for our "Winforms" apps.
Now, we wan't to call it from our Android/iOS Xamarin projects.
We know that Xamarin doesn't supports wsBinding, so we're are using this config:
Server
<system.serviceModel>
<services>
<service
name="serviceWCF.nameService"
behaviorConfiguration="behavior_base">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="transport"
contract="serviceWCF.nameInterfaceService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="transport">
<security mode="Transport" >
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="behavior_base">
<serviceMetadata httpsGetEnabled="true" httpsGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
We created a proxy from SVCUTIL.EXE, then we have implement manually the async methods, channel creation, because Xamarin doesn't supports dinamic bindings, and so on.
The proxy for our Xamarin client app, it's invoked so:
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
AddressHeader addressHeader2;
AddressHeader[] addressHeaders;
EndpointAddress endpoint;
addressHeader2 = AddressHeader.CreateAddressHeader("nameapp_iOS", "https:\\URL_WCF_Service.svc", 0);
addressHeaders = new AddressHeader[]{ addressHeader2};
endpoint = new EndpointAddress(new System.Uri("https:\\URL_WCF_Service.svc"),addressHeaders);
System.Security.Cryptography.X509Certificates.X509Certificate2 oCert;
oCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(System.IO.File.ReadAllBytes("CertBundle.pfx"), "pass");
Service_MovilClient oProxy = new Service_MovilClient(binding, endpoint);
Service_MovilClient oProxy.ClientCredentials.ClientCertificate.Certificate = oCert
But ... nothing happens... time out....
The server it's ok. The url can be accessed from the iOS emulator. We can use it with only "basicHttpBinding", but, we want to use SSL+Client Certificate.
Any ideas? Now I'm stuck.
It's worthless to spoil more efforts. By now, WCF Xamarin its very short.
I have to settle for with HTTPs and a basic Transport Security (security mode="Transport").
I have to use that Wcf services ... But if you, pathetic human, are reading this prior a new development, use REST services. They have a much better support form Xamarin.
On my Server, running a Windows Authentication WCF application hosted in IIS 7:
IIS Config: Windows Auth : disabled; anonymous: enabled
<system.serviceModel>
<services>
<service name="Services.AccountService" behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="" binding="ws2007HttpBinding" bindingConfiguration="AccountServiceBinding"
contract="Contracts.IAccountService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!--<serviceDebug includeExceptionDetailInFaults="true"/>-->
<serviceMetadata httpGetEnabled="true" httpGetUrl="" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<ws2007HttpBinding>
<binding name="AccountServiceBinding" >
<security mode="Message">
<message clientCredentialType="Windows" />
</security>
</binding>
</ws2007HttpBinding>
</bindings>
</system.serviceModel>
and then I create a MVC4 Application with following code to call WCF service:
WS2007HttpBinding myBinding = new WS2007HttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
EndpointAddress endpoint = new EndpointAddress("http://server/accountservice.svc");
AccountServiceClient _client = new AccountServicesObjects.AccountServiceClient(myBinding, endpoint);
_client.ClientCredentials.Windows.ClientCredential.UserName = "username";
_client.ClientCredentials.Windows.ClientCredential.Password = "password";
var user = _client.GetUserInformation(); // works fine
After I finished this mvc4 application, I deploy this website to the Same server which is running WCF one, when I login, occurs:
System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service.
System.ServiceModel.FaultException:The request for security token could not be satisfied because authentication failed.
on System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
on System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)
how this happend?
It seems your service hasn't been started at all. If you enable tracing you can find an exception. There is an error in your configuration - you have no base address, but you have set HttpGetUrl to true (for that option you have to set base address)
This should work for you:
<service name="Services.AccountService" behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="accountservice.svc" binding="ws2007HttpBinding"
bindingConfiguration="AccountServiceBinding"
contract="Services.IAccountService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/"/>
</baseAddresses>
</host>
</service>
I have a WCF Service which allows only HTTP GET requests:
[WebInvoke(Method="GET", ResponseFormat=WebMessageFormat.Json)]
public string GetAppData()
The service is exposed using webHttpBinding
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="AppSvcBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
I have my client whose config looks like
<system.serviceModel>
<client>
<endpoint address="http://localhost/AppService/Service.svc"
binding="webHttpBinding"
bindingConfiguration="webHttpBindingConfig"
contract="AppSvc.IService"
behaviorConfiguration="AppSvcBehavior"
name="AppSvcClient">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</client>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingConfig">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="AppSvcBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
My client code is a simple
ServiceClient client = new ServiceClient("AppSvcClient");
String result = client.GetAppData();
On executing this code I get the error:
The remote server returned an unexpected response: (405) Method Not Allowed.
I checked with fiddler and found that my client is sending a POST message whereas the service expects a GET hence the error.
I wish to know how to configure the client so that is sends GET request to the service.
Use WebGet instead of WebInvoke
Edit
Start by changing your method to this:
[WebInvoke(Method="GET", ResponseFormat=WebMessageFormat.Json,UriTemplate = "/")]
public string GetAppData()
Make sure that webhttpbinding is specified on the server side.
This fixes it on the server side.
Take a backup of your client code.
On the client side delete the service reference. Make sure that all config is removed.
Then add the service reference again. Now it shoud be OK.
I had a similar problem where the generated proxy service interface on the client was missing the WebGet attribute on my methods.
I added the attribute manually and it resolved the problem.
So it seems like the best current solution is to extract the service interfaces into a separate assembly and then share this assembly between the server and its clients.
The automatic proxy generator seems to be buggy.
This a question that already has been discussed a couple of times on SO but I couldn't find any suitable solution to my problem. I have a WCF service hosted on an external server (other domain) and I'm trying to consume it from a command line application. I receive the following error:
The request for security token could not be satisfied because authentication failed.
The service is configured inside a web.config file:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_IRun">
<security mode="None">
<message clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix="http://www.domain.net"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior name="calculadora.SOA.RunBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="calculadora.SOA.RunBehavior" name="calculadora.SOA.Run">
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc" binding="wsHttpBinding" contract="calculadora.SOA.IRun">
<identity>
<dns value="domain.net"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
On the client side, I create a custom binding to connect to the service. Here is the security configuration:
standardBinding.Security.Mode = SecurityMode.None;
standardBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
standardBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
standardBinding.Security.Transport.Realm = "";
standardBinding.Security.Message.ClientCredentialType = MessageCredentialType.None;
standardBinding.Security.Message.NegotiateServiceCredential = false;
standardBinding.Security.Message.EstablishSecurityContext = false;
standardBinding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;
I'm not using any security mechanism for authentification but still, the service seems to be expecting one. When working on different domains, is it mandatory to use a basic authentification?
EDIT: I wasn't referencing any binding configuration at my endpoint. Once the reference was set, I received another message error:
{"The message with Action 'http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue' cannot be processed at the
receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract
mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the
receiver. Check that sender and receiver have the same contract and the same binding (including security
requirements, e.g. Message, Transport, None)."}
The issue was caused by my client's binding. While I was creating my custom binding using the standard 'WSHttpBinding', the 'SecurityMode' property was set to 'Message' instead of 'None'. Now the code looks like the following and the service finally works:
WSHttpBinding standardBinding = new WSHttpBinding(SecurityMode.None, false);
CustomBinding myCustomBinding = new CustomBinding(standardBinding);
Many thanks to marc_s!
I think the problem is your service endpoint definition:
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc"
binding="wsHttpBinding" contract="calculadora.SOA.IRun">
You are using the standard wsHttpBinding - which defaults to integrated Windows security as message security.
While you do define a binding configuration (called wsHttpBinding_IRun), you're not referencing it in your endpoint definition - thus it doesn't come into play. You need to extend your service endpoint definition with a bindingConfiguration attribute like so:
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc"
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_IRun"
contract="calculadora.SOA.IRun">
in order to actually use your defined binding configuration (including the security settings).
I ran into the same issue and after a whole day invested, finally I figure out how to fix. The key is put establishSecurityContext="false" into message tag.
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" establishSecurityContext="false" />
</security>
I've been trying to get WCF security working for my project, and have had little luck. I'm trying to create a service that uses net.tcp as the binding, and does both message and transport security. Message security is done using username and password and transport security is done (supposedly!) using certificates.
For my development testing, I created my own certificate authority and placed this certificate in my computer's trusted store (LocalMachine). I then created two certificates, each signed by my certificate authority, one for the service to use, and one for the client app to use. I placed both of these in the Personal store (My) in LocalMachine. Then, for testing I created a random certificate that wasn't signed by my certificate authority (and therefore is untrusted) and placed that in the Personal store in LocalMachine. I used makecert to create these certificates.
I then configured the client app that connects to the service to use the invalid untrusted certificate as its client certificate. The service is set (supposedly) to check the client certificates using chain trust. However, this client is able to connect and successfully talk to the service! It should be being rejected, because its certificate is untrusted!
I don't know what's causing this behaviour, so I submit the issue to you guys to see what you make of it. Here are my WCF configurations:
Service conf:
<system.serviceModel>
<services>
<service behaviorConfiguration="DHTestBehaviour" name="DigitallyCreated.DHTest.Business.DHTestBusinessService">
<endpoint address="" binding="netTcpBinding" contract="DigitallyCreated.DHTest.Business.IDHTestBusinessService" bindingConfiguration="DHTestNetTcpBinding" bindingNamespace="http://www.digitallycreated.net/DHTest/v1" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8090/"/>
<add baseAddress="http://localhost:8091/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DHTestBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="DHTestMembershipProvider"/>
<serviceCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=business.dhtestDHTest.com" />
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="DHTestRoleProvider" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="DHTestNetTcpBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
<transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign"/>
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
Client Conf:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IDHTestBusinessService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288"
maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Certificate" protectionLevel="EncryptAndSign" />
<message clientCredentialType="UserName" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="DHTestBusinessServiceEndpointConf">
<clientCredentials>
<clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" findValue="CN=invalid"/>
<serviceCertificate>
<authentication revocationMode="NoCheck" trustedStoreLocation="LocalMachine"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="net.tcp://phoenix-iv:8090/" binding="netTcpBinding"
behaviorConfiguration="DHTestBusinessServiceEndpointConf"
bindingConfiguration="NetTcpBinding_IDHTestBusinessService"
contract="DHTest.NetTcp.Business.IDHTestBusinessService"
name="NetTcpBinding_IDHTestBusinessService">
<identity>
<dns value="business.dhtest.com" />
</identity>
</endpoint>
</client>
</system.serviceModel>
The client username/password auth code:
DHTestBusinessServiceClient client = new DHTestBusinessServiceClient();
client.ClientCredentials.UserName.UserName = "ratfink";
client.ClientCredentials.UserName.Password = "testpassword";
Thank you for your help in advance.
EDIT (2009/06/01):
One of my friends pointed me towards a blog that answers the question as to why this is occurring. Apparently, when you specify TransportWithMessageCredential is means exactly that: Transport with Message Credentials only. This is why my certificates are being ignored on the transport level.
However, I don't consider the issue complete and closed, because I still want to do this. :) I'm going to look into custom certificate validators that I think I can plug in and see if that works. I'll get back to you all with the results.
EDIT (2009/06/08):
No, custom certificate validators don't work either. WCF simply doesn't call them.
I found a solution to my problem, however, it turned out to be a lot nastier than I expected.
Basically, to achieve both Transport and Message credential checking you need to define a custom binding. (I found info to this effect here).
I found the easiest way to do this is to continue doing your configuration in the XML, but at runtime copy and slightly modify the netTcp binding from the XML configuration. There is literally one switch you need to enable. Here's the code on the service side and on the client side:
Service Side
ServiceHost businessHost = new ServiceHost(typeof(DHTestBusinessService));
ServiceEndpoint endpoint = businessHost.Description.Endpoints[0];
BindingElementCollection bindingElements = endpoint.Binding.CreateBindingElements();
SslStreamSecurityBindingElement sslElement = bindingElements.Find<SslStreamSecurityBindingElement>();
sslElement.RequireClientCertificate = true; //Turn on client certificate validation
CustomBinding newBinding = new CustomBinding(bindingElements);
NetTcpBinding oldBinding = (NetTcpBinding)endpoint.Binding;
newBinding.Namespace = oldBinding.Namespace;
endpoint.Binding = newBinding;
Client Side
DHTestBusinessServiceClient client = new DHTestBusinessServiceClient();
ServiceEndpoint endpoint = client.Endpoint;
BindingElementCollection bindingElements = endpoint.Binding.CreateBindingElements();
SslStreamSecurityBindingElement sslElement = bindingElements.Find<SslStreamSecurityBindingElement>();
sslElement.RequireClientCertificate = true; //Turn on client certificate validation
CustomBinding newBinding = new CustomBinding(bindingElements);
NetTcpBinding oldBinding = (NetTcpBinding)endpoint.Binding;
newBinding.Namespace = oldBinding.Namespace;
endpoint.Binding = newBinding;
You'd think that'd be it, but you'd be wrong! :) This is where it gets extra lame. I was attributing my concrete service methods with PrincipalPermission to restrict access based on roles of the service user like this:
[PrincipalPermission(SecurityAction.Demand, Role = "StandardUser")]
This started failing as soon as I applied the above changes. The reason was because the
OperationContext.Current.ServiceSecurityContext.PrimaryIdentity
was ending up being an unknown, username-less, unauthenticated IIdentity. This was because there are actually two identities representing the user: one for the X509 certificate used to authenticate over Transport, and one for the username and password credentials used to authenticate at Message level. When I reverse engineered the WCF binaries to see why it wasn't giving me my PrimaryIdentity I found that it has an explicit line of code that causes it to return that empty IIdentity if it finds more than one IIdentity. I guess it's because it's got no way to figure out which one is the primary one.
This means using the PrincipalPermission attribute is out the window. Instead, I wrote a method to mimic its functionality that can deal with multiple IIdentities:
private void AssertPermissions(IEnumerable<string> rolesDemanded)
{
IList<IIdentity> identities = OperationContext.Current.ServiceSecurityContext.AuthorizationContext.Properties["Identities"] as IList<IIdentity>;
if (identities == null)
throw new SecurityException("Unauthenticated access. No identities provided.");
foreach (IIdentity identity in identities)
{
if (identity.IsAuthenticated == false)
throw new SecurityException("Unauthenticated identity: " + identity.Name);
}
IIdentity usernameIdentity = identities.Where(id => id.GetType().Equals(typeof(GenericIdentity))).SingleOrDefault();
string[] userRoles = Roles.GetRolesForUser(usernameIdentity.Name);
foreach (string demandedRole in rolesDemanded)
{
if (userRoles.Contains(demandedRole) == false)
throw new SecurityException("Access denied: authorisation failure.");
}
}
It's not pretty (especially the way I detect the username/password credential IIdentity), but it works! Now, at the top of my service methods I need to call it like this:
AssertPermissions(new [] {"StandardUser"});
check out the Codeplex - Intranet Section that provides checklists for different scenarios. The other thing to mention is that netTcpBindings are not supported for use within IIS5.0 and IIS6.0 - see 3rd paragraph here, only IIS7.0+.