Hi,
I am trying to bind soap sercurity header tag with usernametoken. I am using SHA1 algorithm to hashing the password with using datetime and 16 byte nonce; instead I have tried with Microsoft.Web.Services3.Security.Tokens - UsernameToken class also to generate nonce.
I am binding the SOAP message in stringbuilder and using
MSXML2 component's
ServerXMLHTTPClass to send request and response from the server.
this is my soap message building method.
sb.Append("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsdl=\"http://www.onvif.org/ver10/device/wsdl\">");
credential = AuthenticationCore("service", "service");
sb.Append("<soap:Header>");
sb.Append("<wsse:Security soap:mustUnderstand = \"true\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">");
sb.Append("<wsse:UsernameToken wsu:Id=\"UsernameToken-" + System.Guid.NewGuid() + "\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">");
sb.Append("<wsse:Username>" + credential.UserName + "</wsse:Username>");
sb.Append("<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + credential.Password + "</wsse:Password>");
sb.Append("<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + credential.Nonce + "</wsse:Nonce>");
sb.Append("<wsu:Created>" + credential.Created + "</wsu:Created>");
sb.Append("</wsse:UsernameToken>");
sb.Append("</wsse:Security>");
sb.Append("</soap:Header>");
//sb.Append(GetHeadder());
sb.Append("<soap:Body>");
if (BodyContent != null)
sb.Append(BodyContent.ToString());
sb.Append("</soap:Body>");
sb.Append("</soap:Envelope>");
and this is my method which i am using to encrypt the password and generate nonce.
internal const int NonceLength = 0x10;
private RNGCryptoServiceProvider Rand;
private byte[] CreateNonce()
{
byte[] buf = new byte[NonceLength];
Rand.GetBytes(buf);
return buf;
}
private UserCredential AuthenticationCore(string username, string password)
{
UserCredential Return = new UserCredential();
UsernameToken usernameToken = new UsernameToken(username, password, PasswordOption.SendHashed);
try
{
byte[] nonce = usernameToken.Nonce;
string createtime;
createtime = DateTime.UtcNow.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFF") + "Z";
string expiretime = DateTime.UtcNow.AddMinutes(5).ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFF") + "Z";
byte[] digestbuf = new byte[nonce.Length + Encoding.Unicode.GetByteCount(createtime + password)];
nonce.CopyTo(digestbuf, 0);
Encoding.Unicode.GetBytes(createtime + password).CopyTo(digestbuf, nonce.Length);
SHA1 sha1 = SHA1.Create();
string digest = Convert.ToBase64String(sha1.ComputeHash(digestbuf));
Return.UserName = username;
Return.Password = digest;
Return.Nonce = Convert.ToBase64String(nonce);
Return.Created = createtime;
Return.Expaire = expiretime;
}
catch
{
}
return Return;
}
public struct UserCredential
{
public string UserName;
public string Password;
public string Nonce;
public string Created;
public string Expaire;
}
but while send the Soap message request, it alway response as Authentication failed.
Request:
="1.0"="utf-8"
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsdl="http://www.onvif.org/ver10/device/wsdl">
<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-3ae8d972-d014-47b0-858b-2364f6119763" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>service</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">jJdUs+AXDHZou8EmltlzwwNbe/M=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">V0db+It+XZpH5s2mrh1ylA==</wsse:Nonce>
<wsu:Created>2010-11-22T06:43:47.61Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<tds:GetDeviceInformation xmlns:tet="http://www.onvif.org/ver10/events/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver10/imaging/wsdl" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" />
</soap:Body>
</soap:Envelope>
Response:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:ter="http://www.onvif.org/ver10/error">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<SOAP-ENV:Code>
<SOAP-ENV:Value>SOAP-ENV:Sender</SOAP-ENV:Value>
<SOAP-ENV:Subcode>
<SOAP-ENV:Value>ter:NotAuthorized</SOAP-ENV:Value>
<SOAP-ENV:Subcode>
<SOAP-ENV:Value>ter:SenderNotAuthorized</SOAP-ENV:Value>
</SOAP-ENV:Subcode>
</SOAP-ENV:Subcode>
</SOAP-ENV:Code>
<SOAP-ENV:Reason>
<SOAP-ENV:Text>The requested action requires authorization</SOAP-ENV:Text>
</SOAP-ENV:Reason>
<SOAP-ENV:Node>http:
<SOAP-ENV:Role>http:
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I don't know where I am doing the mistake :(
Can anyone help me to solve this problem?