I have an existing WCF service that uses Transport security with Negotiate authentication with windows credentials.
The client uses impersonation with credentials accepted by the remote service. Now I want to put a WCF router in the middle.
The problem I’m facing is how to get the router to pass the client credentials the service.
Well, if I configure the router custom binding with AuthenticationSchemes.Negotiate, it will fail authentication because the router is unfamiliar with the client credentials. Then switched to AuthenticationSchemes.Anonymous and now the client can connect with the router, but the problem is there are no credentials that the router use in the channel to impersonate the client with the service (in fact this is a binding configuration error: The contract operation ‘ProcessRequest’ requires Windows identity for automatic impersonation. A Windows identity that represents the caller is not provided by binding (‘CustomBinding’,’http://tempuri.org/’) for contract (‘IRequestReplyRouter’,’http://schemas.microsoft.com/netfx/2009/05/routing’
I see in other posts that the credentials are hardcoded in the binding, not possible in my case due to security.
Logically, below is what I need to do, but how can I pass the credentials in the context
client –> (anonymous) ——> router –> (impersonate with creds) –> service
+ windows creds (fwd creds)
I’ve been going around in circles, appreciate any guidance here folks.
**Router service configuration: **
ServiceHost serviceHost = new ServiceHost(typeof(RoutingService), new Uri[] { new Uri($"https://{routerHost}/routingservice/router") });
CustomBinding routerBinding = new CustomBinding();
routerBinding.Elements.Add(new ReliableSessionBindingElement
{
InactivityTimeout = TimeSpan.FromMinutes(22)
});
routerBinding.Elements.Add(new HttpsTransportBindingElement
{
AuthenticationScheme = AuthenticationSchemes.Anonymous,
MaxReceivedMessageSize = 100000000,
MaxBufferPoolSize = 40000000,
});
ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(typeof(IRequestReplyRouter), routerBinding, string.Empty);
endpoint.Behaviors.Add(new MessageLogger("Router"));
The client endpoint the router will route messages to
CustomBinding remoteServiceBinding = new CustomBinding();
remoteServiceBinding.Elements.Add(
new ReliableSessionBindingElement
{
MaxRetryCount = 15,
Ordered = true,
InactivityTimeout = TimeSpan.FromMinutes(22)
});
remoteServiceBinding.Elements.Add(
new HttpsTransportBindingElement
{
AuthenticationScheme = AuthenticationSchemes.Negotiate,
MaxReceivedMessageSize = 100000000,
MaxBufferPoolSize = 40000000,
});
EndpointAddress clientAddress = new EndpointAddress("https://<remoteservice url>");
ContractDescription contract = ContractDescription.GetContract(typeof(IRequestReplyRouter));
ServiceEndpoint client = new ServiceEndpoint(contract, remoteServiceBinding, clientAddress);
List<ServiceEndpoint> endpointList = new List<ServiceEndpoint>() { client };
RoutingConfiguration rc = new RoutingConfiguration(){ RouteOnHeadersOnly = true };
rc.FilterTable.Add(new MatchAllMessageFilter(), endpointList);
//attach the behavior to the service host
serviceHost.Description.Behaviors.Add(new RoutingBehavior(rc));
serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpsGetEnabled = true });
var serviceAuthorizationBehavior = serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
if (serviceAuthorizationBehavior != null)
{
serviceAuthorizationBehavior.ImpersonateCallerForAllOperations = true;
}
**Client configuration snippet **
NetworkCredential remoteCred = <remote machine domain, username, password>
this.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
this.ClientCredentials.Windows.ClientCredential = remoteCred;
I tried
- message inspectors to inject some security context/headers during BeforeSendRequest
- other bindings on the router to pass client credentials on the message.
- Custom ServiceAuthorization manager
- Passing the credentials using AddBindingParameters (customize Endpoint behavior).
- Messing around with OperationContextScope and ServiceSecurityContext.Current.
Clearly, I’m just trying out hacks…
Ingmar H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.