views:

579

answers:

4

Got a simple WCF demo app that has two console projects--host and client. Both are running on my machine (win 7 box). I'm using the netTcpBinding, which uses windows authentication.

The issue is that authentication is downgrading to NTLM from kerberos, and I can't figure out why.

If I use

<clientCredentials>
   <windows allowNtlm="true" />
</clientCredentials>

on the client side, everything is cool. But if I change that to false, I get the following exception:

SecurityNegotiationException: The remote server did not satisfy the mutual authentication requirement.

This suggests that kerberos is failing and since the client won't allow NTLM the call results in an exception being thrown.

Is this an issue with the project, or is it an external issue caused by the configuration of my development machine?


Solution:

Apparently, I have to specify the identity of the server within the client configuration. In my case, the server is running under my identity, so I modify the client thusly:

<client>
  <endpoint address="net.tcp://dev7.HurrDurr.com:12345/MyService" 
            binding="netTcpBinding" 
            bindingConfiguration="MyBindingConfigurationLol" 
            behaviorConfiguration="HurrDurrServiceEndpoint" 
            contract="ShaolinCore.ICommunicationService">
    <!-- start changes here -->
    <identity>
      <userPrincipalName value="myusername@mydomain"/>
    </identity>
    <!-- end changes here -->
  </endpoint>
</client>

I'm not sure why this fixes the issue. Okay, now on the client side I fully trust the server (hey, I know that guy!). But since NTLM is less secure than kerberos, why isn't it the other way around? If I don't fully trust the server, I use kerberos, otherwise ntlm is fine.

Or, OTOH, if I don't fully trust the server why does it work at all? "SecurityException: Endpoint identity not set. WCF cannot trust the identity of the server and will not transmit client identity."

+1  A: 

How is the server configured? Do you have the <authentication mode="Windows"/> and <identity impersonate="true"/> in the config file?

You set the authentication mode via the authentication tag in the config file:

<configuration>
  <system.web>
    <authentication mode="Windows" />
  </system.web>
</configuration>
Hogan
I think these only apply to http bindings. I'm specifying my clientCredentialType is Windows, however.
Will
Again, it works if the client allows for ntlm, it fails otherwise (meaning, I believe, kerberos isn't available).
Will
AFAIK they don't only apply to http.
Hogan
I don't see any authenticationMode in anything to do with tcp. I didn't, however, see identity either, and that was eventually the solution. Where, exactly in a tcp binding, do you set authentication mode (in xml, not in code kthx)?
Will
This is a console app; I don't think how I log into a website has much to do with what I'm experiencing...
Will
+1  A: 

Maybe this page on MSDN - Debugging Windows Authentication Errors - helps you figure out what's going on - seems to be quite tricky as to when NTLM vs. Kerberos is being used.

marc_s
k... domain user on both ends, check. Fully qualified URL, updated, no difference. Added identity/UPN... no difference. Configuring SPN identity on client... BINGO!
Will
@Will: Cool, I was just about to suggest you check the SPNs on the server and client.
Hogan
+1  A: 

Fyi via MSDN: netTcpBinding: The default binding uses transport security with negotiated authentication. This negotiation attempts to use Kerberos, but if that doesn't work, it'll fall back and use the older NTLM protocol. Kerberos is a great choice if you're in a domain environment; in order to use it, you'll need both your service and clients to be running under domain accounts. You'll also want to configure a service principal name (SPN) for your service.

RandomNoob
So in theory after reading your comments which I didn't read initially, the behavior seems to be by design.
RandomNoob
+2  A: 

When I worked on the IIS4, 5 and 6 development teams we ran into this a lot! For Kerb to work, you need the following conditions to be true:

1) Both parties support kerb (all supported versions of Windows support Kerb today)

2) Machines auth to Active Directory

3) Service Principal Names (SPNs) registered for the server endpoint. In the "good old days" you had to do this by hand using SetSPN.exe. An SPN is just an endpoint that Kerb will connect to; it needs this data to support mutual authn. Most apps will call the approp API to this work for you (DsWriteAccountSpn)

If any of the steps above are not true, Windows will usually default to NTLM, whcih gives you only client authentication.

Hope that helps! - Michael

Michael Howard-MSFT
I've read a book or two about windows security, and its still confusing sometimes. I don't understand how WCF handles mutual authentication as well, so it makes it doubly hard. Why must I provide the server UPN/SPN/DNS to enable kerb on the client? If I don't fully trust the server, why is ntlm better than kerb? Or does the client need to provide the service identity to a third party? Why can't the service provide it directly? Why does my head hurt?
Will
Kerb needs to authenticate the client and the server and by that I mean the *computers*. When your client code (WCF) makes a request to connect to a service it needs to know *exactly* what it's connecting to, so an admin needs to add the SPN for the server app to AD - in essence you're saying to Kerb "I need to connect to this SPN". In many cases, the server side of the equation *WILL* regeister an SPN but only if it has the ability to do so.NTLM is not better than Kerb, NTLM authenticates a client only, so the server knows who you are, but you have no clue who you're connecting to.
Michael Howard-MSFT