WCF Net.tcp with sspi fails unless client and server using same windows Identity
Asked Answered
U

2

14

I have a WCF Service being hosted by a windows service. The client app succeeds if I log on to the client machine using the same credentials as the service is running under, but it fails with an exception if I am logged in with any other valid domain account.

I have two accounts that I am testing with, one is an ordinary user account and the other account is an admin account. I have tried all four combinations listed below:

                   Server account
   CLient      RegUser    AdminAcct   
  RegUser     Succeeds      Fails   
 AdminAcct     Fails       Succeeds    

As you can see it cannot be an admin issue as the system works when both client and server are running under the non-admin account. In both cases where it fails I get the same exception, on the client, with no indication of anything happening in the server logs:

"A call to SSPI failed. see inner exception"

The inner exception is "The target principle name is incorrect."

I have registered the accounts as SPNs.

The problem only occurs from my client app, but not when I use the WCVFTestClient.exe which ships with Visual Studio.

The exception, in the WCF Trace log, is

"System.ServiceModel.Security.SecurityNegotiationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

with a message:

"Authentication failed on the remote side (the stream might still be available for additional authentication attempts)."

The stack trace is at the bottom: What is wrong ?

stack trace


System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeAcceptor.OnAcceptUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity) System.ServiceModel.Channels.StreamSecurityUpgradeAcceptorBase.AcceptUpgrade(Stream stream) System.ServiceModel.Channels.InitialServerConnectionReader.UpgradeConnection(IConnection connection, StreamUpgradeAcceptor upgradeAcceptor, IDefaultCommunicationTimeouts defaultTimeouts) System.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ServerFramingDuplexSessionChannel.OnOpen(TimeSpan timeout) System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) System.ServiceModel.Dispatcher.ChannelHandler.OpenAndEnsurePump() System.Runtime.ActionItem.DefaultActionItem.TraceAndInvoke() System.Runtime.ActionItem.CallbackHelper.InvokeWithoutContext(Object state) System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped) System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

Ululate answered 25/3, 2013 at 0:3 Comment(0)
U
16

Found the answer. My problem was a combination of two factors.

  1. When using the net.tcp binary WCF protocol, the Client Security Mode determines whether NTLM or Kerberos is used for authentication. If you set Client Security Mode to "Transport", Authentication uses NTLM and only one hop is possible. If you try to have the WCF Server talk to a third server, (like a database), it will fail. Using SecurityMode = "Message", otoh, causes the WCF server to use Kerberos, which allows multiple hops...

  2. The second issue was related to what I was doing on the client in the binding. WCF protocol net.tcp requires that when instantiating the endpoint on the client, you must specify an "endpoint identity" (see code below) . I had wrongly assumed this was somehow related to authentication, and was, therefore, the identity of the currently logged on user (Windows Principal) on the client.

        var epId = EndpointIdentity.CreateUpnIdentity(userPrincipalName);
        var ep = new EndpointAddress(new Uri(url), epId):
    

    No... The identity which must be specified in the creation of the endpoint on the client must be the identity the server is running under. This is why the code worked whenever I was logged on to the client with the same user as the service was running under, and failed when the client was a different user.

    I still do not understand why this user identity (of the service account) must be specified in the endpoint on the client. What function on the server is this data needed for?

Ululate answered 31/3, 2013 at 14:51 Comment(6)
Thanks a lot for this answer. After hours and hours of try-and-error I tried this solution and it works like a charm! If we'll ever meet, I'll give you a beer ;-)Tasimeter
You're very welcome! Where do I go to get my beer? <grin/>Ululate
According to your profile I think we won't meet in near future...but never ending thanks will follow you ;-)Tasimeter
#2 is the main reason this failed. When using Windows auth the identity of the server is also validated. If you ran your service as SYSTEM or NETWORK SERVICE it could access the machine SPN and you shouldn't need to explicitly provide the UPN as it will default to expecting the machine SPN. Since you're running a custom account you need to tell your client about it so it can authenticate the serverPlanography
#1 it's wrong to say you need message security to talk to a DB as those comms aren't using WCF. It may have a side effect of triggering Kerberos which maybe an issue for you. A better way to force Kerberos is to set AllowNtlm to false (google it).Planography
Thanks guy, you save my day!Megara
G
1

Regarding the second point, the client is not required to run under the same Windows account of the server in order to be authenticated successfully, and it's not required to manually specify the account name in the request. From what I understand, WCF authentication is mutual, meaning the client is verifying the server as well.

The error you received is probably due to failure on the client side. If you configure the service endpoint of the client to provide a ServicePrincipalName, the problem might well be resolved. I found this article pretty helpful to solve the same issue I encountered.

Gerger answered 19/5, 2016 at 6:8 Comment(1)
link isn't validMadisonmadlen

© 2022 - 2024 — McMap. All rights reserved.