0

I am attempting to hit a WSE secured web service using WCF. The SOAP header I need to generate to do this should contain a username, password, nonce, and created date... Here is a an example of a soap UI header that I use to hit the same service...

   <soap:Header>
      <wsse:Security soap:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:UsernameToken wsu:Id="UsernameToken-2" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsse:Username>----------</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">----------</wsse:Password>
            <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Hozef94FFwOhuiF5QixaMQ==</wsse:Nonce>
            <wsu:Created>2012-08-21T13:26:03.642Z</wsu:Created>
         </wsse:UsernameToken>
      </wsse:Security>
   </soap:Header>

Now I found a tutorial that was pretty usefull. usefull tutorial

I have successfully implemented it... But I am now sticking the SOAP body into the soap header and there isn't a nonce generated.

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
    <s:Header>
        <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo9VZylDHg5JMgjsNnWLhATkAAAAA+YtOxHdh0Uqd4a64raX/nIzYz20mPHlBv4Wk5S8d5PsACQAA</VsDebuggerCausalityData>
        <wsse:Security s:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
            <UsernameToken xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                <Username>------------</Username>
                <Password>************</Password>
            </UsernameToken>
        </wsse:Security>
        <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <GetOrganizations xmlns="http://------------------------/businessobjects/messaging/">
                <personId xmlns="">0</personId>
                <typeId xmlns="">
                    <int>1</int>
                    <int>2</int>
                    <int>3</int>
                    <int>4</int>
                </typeId>
            </GetOrganizations>
        </s:Body>
    </s:Header>
</s:Envelope>

Don't know why it is doing this. I followed the tutorial to the letter. My Repository getting everything...

using (DistListServiceReference.DistributionListClient dlc = new DistListServiceReference.DistributionListClient())
            {
                try
                {
                    PasswordDigestBehavior behavior = new PasswordDigestBehavior("********", "********");                            
                    dlc.Endpoint.Behaviors.Add(behavior);

                    GetDistributionLists gdl = new GetDistributionLists();

                    gdl.PersonID = 0;

                    GetDistributionListsResponse gdlr = new GetDistributionListsResponse();

                    gdlr = dlc.GetDistributionLists(gdl);
                    return gdlr;
                }
                catch (Exception e)
                {
                    dlc.Abort();
                    return null;
                }
            }

My PasswordDigentInspector

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
        {
            // Use the WSE 3.0 security token class
            UsernameToken token = new UsernameToken(this.Username, this.Password, PasswordOption.SendPlainText);
            WseHeader header = new WseHeader(this.Username, this.Password);

            // Serialize the token to XML
            XmlElement securityToken = token.GetXml(new XmlDocument());           

            MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken", securityToken, false);
            request.Headers.Add(header);

            // complete
            return Convert.DBNull;
        }

How I apply client behavior

public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(new PasswordDigestMessageInspector(this.Username, this.Password));
        }

Everything is pretty much there. I am not seing where the body is being injected into the header. Any body have any ideas?

UPDATE: Debugging I am looking at the the actual header that I inject into the soap message and this is what I see...

{<wsse:Security s:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <UsernameToken xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <Username>**********</Username>
    <Password>************</Password>
  </UsernameToken>} System.ServiceModel.Channels.MessageHeaderInfo {TestDistListApplication.Repository.WseHeader}

Just looking at that, there is no nonce, I could build it programmatically, but I am not sure if that is a good idea. Especially since there is a nonce already and a create date in the securityToken... Not sure why they don't appear in the header though...

<wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">MedTrak_Dev</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">uncJUN132012</wsse:Password>
<wsse:Nonce xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">mvy9nUfF+rnT3oTasDBqxg==</wsse:Nonce>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2012-08-28T13:30:42Z</wsu:Created>

I have the debugger stopped and I am watching both those variables. What might cause the header not to have those things and the the WSEHeader to have them? Looks like I will have to debugg that.

Community
  • 1
  • 1
SoftwareSavant
  • 9,467
  • 27
  • 121
  • 195

1 Answers1

1

Without running your code myself it is a little tricky to understand why my example doesn't work in your scenario. However, in a attempt to debug this I would try the following:

Stick a breakpoint on this line:

XmlElement securityToken = token.GetXml(new XmlDocument());

And after stepping through this line, see what the securityToken XML looks like. It is this XML which is being injected into the security header. It isn't any more complicated than that. You coudl create this XML manually if you want. I used the WSE 3.0 classes because I didn't want to hand code the XML myself.

I also notice that your security token definition looks slightly different to mine. My example was:

MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityToken, false);

Yours:

MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken", securityToken, false);

The namespaces are different. Any reason for this?

If the breakpoint added from the step above isn't hit then it would suggest that the behavior isn't actually being applied. In which case, you'll probably need to double check your configs to make sure that the behavior is correctly applied on the client. Alternatively (as my example shows) you can programatically add the custom behavior before sending the message.

I recommend to anyone dealing with WCF issues, that they first turn on verbose logging and also use fiddler to see what is actually going over the wire.

Rebecca
  • 13,914
  • 10
  • 95
  • 136
  • Actually now that I look at it (the inner XML that is), I see the nonce and the created date. I wonder why on earth my body is being injected into the header? – SoftwareSavant Aug 28 '12 at 13:33
  • Also, about the header being different, I am not sure why I changed that now that I think about it. I was experiementing with different things I guess. – SoftwareSavant Aug 28 '12 at 13:36
  • I have no clue why it is doing this... I stop where you tell me, but I don't see any where in there where it injects the body into the header... I have to be missing something. – SoftwareSavant Aug 28 '12 at 13:52
  • I was calling the wrong header it would seem. That's what happens when you do more than one tutorial at a time. Thanks. – SoftwareSavant Aug 29 '12 at 12:30