[ACCEPTED]-WCF: Adding Nonce to UsernameToken-web-services

Accepted answer
Score: 22

To create the nonce, I had to change a few 4 things

First, added a custom binding in my 3 config

<system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="myCustomBindingConfig">
          <security includeTimestamp="false" 
                    authenticationMode="UserNameOverTransport" 
                    defaultAlgorithmSuite="Basic256" 
                    requireDerivedKeys="true"
                    messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
          </security>
          <textMessageEncoding messageVersion="Soap11"></textMessageEncoding>
          <httpsTransport maxReceivedMessageSize="2000000000" />
        </binding>
      </customBinding>
    </bindings>
</system.serviceModel>

<client>
    <endpoint address="https://..." [other tags] 
        binding="customBinding" bindingConfiguration="OrangeLeapCustomBindingConfig"/>
</client>

Then, take this code found here: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/4df3354f-0627-42d9-b5fb-6e880b60f8ee and 2 modify it to create the nonce (just a random 1 hash, base-64 encoded)

protected override void WriteTokenCore(System.Xml.XmlWriter writer, System.IdentityModel.Tokens.SecurityToken token)
{
    Random r = new Random();
    string tokennamespace = "o";
    DateTime created = DateTime.Now;
    string createdStr = created.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
    string nonce = Convert.ToBase64String(Encoding.ASCII.GetBytes(SHA1Encrypt(created + r.Next().ToString())));
    System.IdentityModel.Tokens.UserNameSecurityToken unToken = (System.IdentityModel.Tokens.UserNameSecurityToken)token;
    writer.WriteRaw(String.Format(
    "<{0}:UsernameToken u:Id=\"" + token.Id + "\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" +
    "<{0}:Username>" + unToken.UserName + "</{0}:Username>" +
    "<{0}:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" +
    unToken.Password + "</{0}:Password>" +
    "<{0}:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" +
    nonce + "</{0}:Nonce>" +
    "<u:Created>" + createdStr + "</u:Created></{0}:UsernameToken>", tokennamespace));
}

protected String ByteArrayToString(byte[] inputArray)
{
    StringBuilder output = new StringBuilder("");
    for (int i = 0; i < inputArray.Length; i++)
    {
    output.Append(inputArray[i].ToString("X2"));
    }
    return output.ToString();
}
protected String SHA1Encrypt(String phrase)
{
    UTF8Encoding encoder = new UTF8Encoding();
    SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
    byte[] hashedDataBytes = sha1Hasher.ComputeHash(encoder.GetBytes(phrase));
    return ByteArrayToString(hashedDataBytes);
}
Score: 12

I had the same problem. Instead of the custom 7 token serializer I used a MessageInspector to add the correct 6 UsernameToken in the BeforeSendRequest method. I then used a custom behavior 5 to apply the fix.

The entire process is 4 documented (with a demo project) in my blog post Supporting the WS-I Basic Profile Password Digest in a WCF client proxy. Alternatively, you 3 can just read the PDF.

If you want to follow 2 my progress through to the solution, you'll 1 find it on StackOverflow titled, "Error in WCF client consuming Axis 2 web service with WS-Security UsernameToken PasswordDigest authentication scheme":

Score: 8

It's worth pointing out that Rick Strahl 8 made a blog post (which he references this 7 question) where he explains it all quite 6 clearly and offers solutions for both just 5 Password and also PasswordDigest.

I post 4 this because I found this article originally, couldn't 3 really follow it, and found Rick's post 2 much later. This might save some people 1 some time.

WCF WSSecurity and WSE Nonce Authentication

Score: 7

This article provides sample with full integration of 2 UserNameToken Profile with digested password 1 into WCF security pipeline.

More Related questions