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?
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
See docs for setspn
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With