2
votes

I am migrating a WCF client from .Net Framework to .Net core. I am creating the client derived from ClientBase and using Federation Binding.

Here is binding creation code working in .Net Framework:

private Binding CreateBinding()
{
   var issuerBinding = new WSHttpBinding(SecurityMode.Transport);
   issuerBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

   var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
   binding.Security.Message.IssuedKeyType = SecurityKeyType.SymmetricKey;
   binding.Security.Message.NegotiateServiceCredential = false;
   binding.Security.Message.EstablishSecurityContext = false;

   binding.Security.Message.IssuerAddress = new EndpointAddress(this.stsAddress);
   binding.Security.Message.IssuerBinding = issuerBinding;

   return binding
}

Here is corresponding code in .Net core:

private Binding CreateBinding()
{
   var issuerBinding = new WSHttpBinding(SecurityMode.Transport);
   issuerBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

   var endpointAddress = new EndpointAddress(this.stsAddress);
   var tokenParameters = WSTrustTokenParameters.CreateWS2007FederationTokenParameters(issuerBinding, endpointAddress);
   tokenParameters.KeyType = SecurityKeyType.SymmetricKey;

   var binding = new WSFederationHttpBinding(tokenParameters);
   binding.Security.Message.NegotiateServiceCredential = false;
   binding.Security.Message.EstablishSecurityContext = false;

   return binding;
}

Unfortunately the .net core version does not work - calling the service throws 'The HTTP request was forbidden with client authentication scheme 'Anonymous'.'

It turned out that the request to sts is failing. I created a proxy to intercept the http requests and found following differences in the calls to the sts service:

  1. the .net framework request contains following properties that are missing in .net core version:
<trust:KeyWrapAlgorithm>
   http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p
</trust:KeyWrapAlgorithm>
<trust:EncryptWith>
   http://www.w3.org/2001/04/xmlenc#aes256-cbc
</trust:EncryptWith>
<trust:SignWith>
   http://www.w3.org/2000/09/xmldsig#hmac-sha1
</trust:SignWith>
<trust:CanonicalizationAlgorithm>
   http://www.w3.org/2001/10/xml-exc-c14n#
</trust:CanonicalizationAlgorithm>
<trust:EncryptionAlgorithm>
   http://www.w3.org/2001/04/xmlenc#aes256-cbc
</trust:EncryptionAlgorithm>
  1. trust:BinarySecret element of trust:Entropy is different. The .net framework version contains type attribute Type="http://docs.oasis-open.org/ws-sx/ws-trust/200512/Nonce" which is missing in the .net core version. According to the WS-Trust documentation the default value is SymmetricKey.
  2. The .net core request contains trust:TokenType element which is missing in the .net framework version
<trust:TokenType>
   http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0
</trust:TokenType>

How can i set up a proper binding to make it work in .net core?

2

2 Answers

0
votes

Core does not support Wshttpbinding, wcf only supports BasicHttpBinding, CustomBinding, NetHttpBinding, NetTcpBinding:

enter image description here

I suggest you continue to use the .net framework or modify the server-side binding.

For more information about WCF Features in core, you can refer to this link.

0
votes

It turned out that the .net core WCF client didn't send the certificate with the request. .net core checks if certificate has a private key and skips it if not. https://github.com/dotnet/corefx/blob/fe7adb2bf92bba926268c2e9f562b11c84932a07/src/Common/src/System/Net/Security/CertificateHelper.cs#L39-L42

if (!cert.HasPrivateKey)
{
   continue;
}

I was getting the certificate from Azure Key Vault which by default returns it without the private key. Changing it to include the private key resolved the issue.

My .net framework application used the same method of getting the certificate (so it didn't have the private key either), but it was able to obtain the private key from my Local machine store where the certificate was installed.