Friday, April 20, 2012

How to implement a Security token in a WCF soap response?

I am implementing an API from a bank and they require a security token to be provided. In the header of every soap message there is something which looks as follows:



<soapenv:Header>
<tpw:BinarySecurityToken ValueType="MAC" Id="DesMacToken" EncodingType="Base64" Value="**xvz**"/>
</soapenv:Header>


According to their documentation I need to generate an 8 byte MAC value on the body of each message. The MAC is generated by the CBC-MAC algorithm and DES as the block cipher. The contents of the soapenv:Body tag of each message is used as the data for the MAC calculation.



So my question is how do I get WCF to do this? I have put the following code together to create the MAC value, but am unsure how to get this into the header of every message.



private string GenerateMAC(string SoapXML)
{
ASCIIEncoding encoding = new ASCIIEncoding();

//Convert from Hex to Bin
byte[] Key = StringToByteArray(HexKey);
//Convert String to Bytes
byte[] XML = encoding.GetBytes(SoapXML);

//Perform the Mac goodies
MACTripleDES DesMac = new MACTripleDES(Key);
byte[] Mac = DesMac.ComputeHash(XML);

//Base64 the Mac
string Base64Mac = Convert.ToBase64String(Mac);

return Base64Mac;
}

public static byte[] StringToByteArray(string Hex)
{
if (Hex.Length % 2 != 0)
{
throw new ArgumentException();
}

byte[] HexAsBin = new byte[Hex.Length / 2];
for (int index = 0; index < HexAsBin.Length; index++)
{
string bytevalue = Hex.Substring(index * 2, 2);
HexAsBin[index] = Convert.ToByte(bytevalue, 16);
}

return HexAsBin;
}


Any help will be greatly appreciated.



More info:
The bank has provided a WSDL which I have used as a service reference. An example of a response that is sent:



[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="LogonRequest", WrapperNamespace="http://webservice.com", IsWrapped=true)]
public partial class LogonRequest {

[System.ServiceModel.MessageHeaderAttribute(Namespace="http://webservice.com")]
public DataAccess.BankService.BinarySecurityToken BinarySecurityToken;


The BinarySecurityToken (that goes in the header) looks as follows:



 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.233")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://webservice.com")]
public partial class BinarySecurityToken : object, System.ComponentModel.INotifyPropertyChanged {

private string valueTypeField;

private string idField;

private string encodingTypeField;

private string valueField;

public BinarySecurityToken() {
this.valueTypeField = "MAC";
this.idField = "DesMacToken";
this.encodingTypeField = "Base64";
}




No comments:

Post a Comment