Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use wsHttpBinding with Message security through a load balancer

I have a load-balanced service that uses Message security:

<wsHttpBinding>
  <binding>
    <security mode="Message">
      <message clientCredentialType="Windows" establishSecurityContext="false" />
    </security>
  </binding>
</wsHttpBinding>

All of my calls to this service open and close their own channel, so there's no benefit to establishing a security context.

I am calling the service with a WSHttpBinding that matches the service config:

ws.Security.Mode = SecurityMode.Message;
ws.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
ws.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
ws.Security.Message.EstablishSecurityContext = false;

This works sometimes, but sometimes I get errors such as

The security context token is expired or is not valid. The message was not processed.

or

The request for security token has invalid or malformed elements.

I finally found that setting EstablishSecurityContext to false doesn't actually prevent security context tokens from being used. Our load balancer doesn't currently use sticky sessions, and I'm trying to avoid going that route.

I did find that I should be able to set NegotiateServiceCredential to false on the client to allow for the load balancer without sticky sessions. My service is already running under an AD account, and I can see it in the WSDL:

<Upn>User@Domain</Upn>

However, when I try to add the service identity to my client

EndpointIDentity.CreateUpnIdentity("User@Domain")

I get the following error:

Authenticating to a service running under a user account which requires Kerberos multilegs, is not supported.

How do I get past this to be able to make a call to my service through the load balancer?

like image 433
zimdanen Avatar asked Nov 08 '22 20:11

zimdanen


1 Answers

According to the documentation for NegotiateServiceCredential, you must run the service using an SPN identity instead of UPN:

If this property is set to false, and the binding is configured to use Windows as a client credential type, the service account must be associated with a Service Principal Name (SPN). To do this, run the service under the NETWORK SERVICE account, or LOCAL SYSTEM account. Alternatively, use the SetSpn.exe tool to create an SPN for the service account. In either case, the client must use the correct SPN in the <servicePrincipalName> element, or by using the EndpointAddress constructor.

Once you configure the SPN that your service is running under, your WSDL should display SPN instead of UPN, then you'll have to modify your client such that: EndpointIdentity.CreateSpnIdentity("service_spn_name")

Update:

The following command should properly configure the SPN:

setspn -A YourSvc/host.server.com domain\AppPoolAcccountName

  • YourSvc = a name identifying your svc
  • host.server.com = fully qualified hostname of the server your service is hosted on

See docs for setspn

like image 179
Dan Ling Avatar answered Nov 24 '22 08:11

Dan Ling