Oscar Jara
Oscar Jara

Reputation: 14187

How to add custom soap headers or use username auth under http?

I am trying to modify and add custom headers to a soap message in the BeforeSendRequest method like this:

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
    {
        MessageHeader header = MessageHeader.CreateHeader("name", "http://myname", "Oscar");
        request.Headers.Add(header);

        return null;
    }

Everything is ok at this point, the header is added in the soap headers like this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="51efbfdb-2187-45b9-81fc-6a38815d5bed" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">d1351a78-a53a-4d32-ad35-fca6d4262adf</ActivityId>
<name xmlns="http://myname">Oscar</name>
</s:Header>

The problem is that I want to add something bigger in the headers and the final result has to be like this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="51efbfdb-2187-45b9-81fc-6a38815d5bed" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">d1351a78-a53a-4d32-ad35-fca6d4262adf</ActivityId>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">username</wsse:Username>
      <wsse:Password xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">password</wsse:Password>
    </wsse:UsernameToken>
</wsse:Security>
</s:Header>

Is there a way to achieve this?

PS. Please guys :-) do not criticize me, I am in the following situation:

When adding this username and password auth, you need to be over https, the problem is that this Java based webservice which I am trying to communicate is under http and I think it is not compliant because according to the 3rd link "It is considered bad practice to pass credentials over an unsecured connection" but they solved it adding the headers in the config file (something I did without success).

I read these links too and tried them. Also when doing things from links 1 and 2, I got a kind of exception in Visual Studio which says something like "It is expected https and not http" that's why I am trying MessageInspectors using BeforeSendRequest method.

  1. Configure WCF for WS-Security with Username over https

  2. http://www.west-wind.com/weblog/posts/2007/Dec/09/Tracing-WCF-Messages

  3. http://www.fransson.net/blog/credentials-over-plain-http-with-wcf/

Upvotes: 1

Views: 7755

Answers (3)

Yaron Naveh
Yaron Naveh

Reputation: 24396

ClearUsernameBinding is the solution

Upvotes: 1

xplat
xplat

Reputation: 8626

I had the same problem, though my service was https. And it should be a configuration matter, you shouldn't need to handle this manually.

Anyway, you don't have to use the MessageInspectors using BeforeSendRequest. You should try and change the config generated code adding some security configuration. WCF will then create what headers you need. Then in code add the credentials and you should be ok.

I imagine that the generated proxy is creating you a customBinding or basicHttpBinding. basicHttpBinding though not supporting the WS-Security specifications, so you should change this either to custom or wsHttpBinding. You can play with and find the correct configuration to gain the desired results.

What I added was "Sample config syntax":

<customBinding>
        <binding name="MessageServerBinding">
          <security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport"
            requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
            <secureConversationBootstrap />
          </security>
........
</binding>
</customBinding>

This is a sample configuration, e.g. you might not need to include a timestamp, or you could need a Nonce which if I remember correctly needs some more effore, not much though.

For check this discussion: WCF: Adding Nonce to UsernameToken

Hope this helps.

Upvotes: 0

Richard Blewett
Richard Blewett

Reputation: 6109

The 3rd parameter of CreateHeader is an object. By default this object is serialized using the DataContractSerializer so if you create a data contract that models the header structure you can pass an instance as the 3rd parameter and it will create the header you want

Upvotes: 0

Related Questions