Chandrabhan
Chandrabhan

Reputation: 24

Calling a SOAP endpoint with security header in .NET Core

.net core- Call a soap service with wss security header

In my .net core class library project I have added reference to a WCF sevrvice(using a wsdl file) and now I have reference class generated under Connected Services. I am able to call the WCF service with a BasicHttpBinding, but the issue is that the server also expect a security element along with the SOAP header

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsse:Security
            xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
            xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <ds:Signature Id="SIG-"
                xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:SignedInfo>                    
                </ds:SignedInfo>
                <ds:SignatureValue>==gMg==</ds:SignatureValue>
                <ds:KeyInfo Id="KI-">                    
                </ds:KeyInfo>
            </ds:Signature>
            <wsu:Timestamp wsu:Id="TS-34A069E7A55FECD03D16098926271579">                
            </wsu:Timestamp>
        </wsse:Security>
        <wsa:Action>http://www.test.com/Namespace/test_action</wsa:Action>
        <wsa:MessageID>uuid:XXX</wsa:MessageID>
    </soapenv:Header>
    </soapenv:Envelope>


So basically I want the SOAP message to have this kind of security tag attached to the header. Please see above sample SOAP.

Thanks in advance :-)

Upvotes: 1

Views: 3017

Answers (3)

Rushabh Master
Rushabh Master

Reputation: 490

I was getting below error

Security requirements are not satisfied because the security header is not present in the incoming message

To those who are finding difficulty with Generated classes by service connection.

Here is what worked for me.

var binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = int.MaxValue;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;

var url = new System.ServiceModel.EndpointAddress("https://example.com/Service.asmx");
var client = new SoapClient(binding, url);
client.ClientCredentials.UserName.UserName = "xxxxxx";
client.ClientCredentials.UserName.Password = "xxxxxx";

Upvotes: 0

Chandrabhan
Chandrabhan

Reputation: 24

So the problem was to add a security header to the SOAP request. I found, that with configuration in your bindings you can send security header as well. You may not need any extra code for it.

<system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ClientBehavior">
          <clientCredentials>
            <clientCertificate findValue="<certificate thumbprint here >" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint"/>
            <serviceCertificate>
              <authentication revocationMode="NoCheck"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>

    <bindings>
      <customBinding>
        <binding name="BasicHttpBinding_IExampleService">
          <security 
                    defaultAlgorithmSuite="Default"                    
                    requireDerivedKeys="false"
                    messageProtectionOrder="SignBeforeEncrypt"
                    requireSignatureConfirmation="false"
                    securityHeaderLayout="Lax"
                    messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                    includeTimestamp="true"
                    >
            <localClientSettings detectReplays="true" />
            <localServiceSettings detectReplays="true" />
          </security>
          <textMessageEncoding messageVersion="Soap11" />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:63454/ExampleService.svc"
        binding="customBinding" bindingConfiguration="BasicHttpBinding_IExampleService"
        contract="ServiceReference1.IExampleService" name="BasicHttpBinding_IExampleService" behaviorConfiguration="ClientBehavior" >
        <identity>
          <certificateReference findValue="<certificate thumbprint here >" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
        </identity>
      </endpoint>
    </client>

  </system.serviceModel>

Upvotes: 0

Ding Peng
Ding Peng

Reputation: 3974

You can do it by building my custom header:

public class SoapSecurityHeader : MessageHeader
    {
        ......
    }

We're then adding this to the SOAP header in the BeforeSendReply method, something like this:

public class MessageInspector : IClientMessageInspector
{
    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        throw new NotImplementedException();
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        SoapSecurityHeader head = new SoapSecurityHeader();
        request.Headers.Add(head);
    }
}

Finally, you need to apply MessageInspector to the service. If you can't apply MessageInspector to the service, you can refer to this link.

Upvotes: 0

Related Questions