dotnet / wcf

This repo contains the client-oriented WCF libraries that enable applications built on .NET Core to communicate with WCF services.
MIT License
1.71k stars 559 forks source link

WS Message mode not supported #5370

Open MenuGamer opened 10 months ago

MenuGamer commented 10 months ago

When dispatching client with WSHttpBinding and SecurityMode.Message the CreateSecurityBindingElement method from System.ServiceModel.MessageSecurityOverHttp will throw platform not supported error.

My old .NET Framework 4.8 project is using the following configuration.

<bindings>
    <wsHttpBinding>
        <binding name="SecureBinding" closeTimeout="23:59:59" openTimeout="23:59:59" receiveTimeout="23:59:59" sendTimeout="23:59:59" maxBufferPoolSize="5242880" maxReceivedMessageSize="1073741824">
            <readerQuotas maxDepth="1000000000" maxStringContentLength="1000000000" maxArrayLength="1000000000" maxBytesPerRead="1000000000" maxNameTableCharCount="1000000000"/>
            <security mode="Message">
                <message clientCredentialType="UserName"/>
            </security>
        </binding>
    </wsHttpBinding>
</bindings>
<client>
    <endpoint name="CustomAuth" address="http://localhost:2000/Service" binding="wsHttpBinding" bindingConfiguration="SecureBinding">
        <identity>
            <dns value="TestCert"/>
        </identity>
    </endpoint>
</client>

I've recreated it in .NET 7.0 manually as followed

// Initialize the default binding
var wsHttpBinding = new WSHttpBinding();
wsHttpBinding.CloseTimeout = TimeSpan.Parse("23:59:59");
wsHttpBinding.OpenTimeout = TimeSpan.Parse("23:59:59");
wsHttpBinding.ReceiveTimeout = TimeSpan.Parse("23:59:59");
wsHttpBinding.SendTimeout = TimeSpan.Parse("23:59:59");
wsHttpBinding.MaxBufferPoolSize = 524288;
wsHttpBinding.MaxReceivedMessageSize = 1073741824;

// Set reader quotas
wsHttpBinding.ReaderQuotas.MaxDepth = 1000000000;
wsHttpBinding.ReaderQuotas.MaxStringContentLength = 1000000000;
wsHttpBinding.ReaderQuotas.MaxArrayLength = 1000000000;
wsHttpBinding.ReaderQuotas.MaxBytesPerRead = 1000000000;
wsHttpBinding.ReaderQuotas.MaxNameTableCharCount = 1000000000;

wsHttpBinding.Security.Mode = SecurityMode.Message;
wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

// Initialize the default endpoint address
Address = new EndpointAddress(new Uri("http://localhost:2000/Service"));

Is this method not supported in .NET 7.0 or is there a workaround.

mconnew commented 10 months ago

SecurityMode.Message is not supported. If you control the client and the server, you could switch to using SecurityMode.TransportWithMessageCredentials and the authentication flow/configuration will continue to work exactly as before. You will need to communicate over https instead of http. Depending on your security requirements, this is likely to give you equal security to what you had before. The difference in security only comes into play if you have a front end which is forwarding requests or you store the requests somewhere for consumption later as the SOAP message itself is no longer encrypted, instead relying on the HTTPS connection to provide secrecy and integrity.

Molochnikov commented 3 months ago

@mconnew , do you know why this code with WSHttpBinding like this...

binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
service.ClientCredentials.UserName.UserName = _iris_options.Value.WSSecurityUser;
service.ClientCredentials.UserName.Password = _iris_options.Value.WSSecurityPassword;

..don't add <wsse:Security> , <wsse:UsernameToken>,<wsse:Username> and <wsse:Password> tags to the header?

Current request XML:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://url</a:Action>
    <a:MessageID>urn:uuid:da52bf77-db42-4af9-827c-edca7375b7c7</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <reserveCard xmlns="http://url">
      <code>1031879</code>
    </reserveCard>
  </s:Body>
</s:Envelope>

Do i need to add this tags manually with IClientMessageInspector?

mconnew commented 3 months ago

I think you don't have your security mode set right. I suspect you need to pass TransportSecurityWithMessageCredential to the constructor.