I have configured a new Azure hosted WCF service with a custom username validator. The validator class will validate username and passwords from an existing aspnetUsers table in an Azure database.
I have configured the service using TransportWithMessageCredentials binding so the clients will be providing their usernames and passwords in clear text in the request.
My code will then look up the user and get their hashed password from the database and then use this to hash the password sent via the service. If they match then allow the request.
to validate the password I am using this code.
public static bool checkPassword(string hashedPassword, string password)
{
byte[] buffer4;
if (hashedPassword == null)
{
return false;
}
if (password == null)
{
throw new ArgumentNullException("password");
}
byte[] src = Convert.FromBase64String(hashedPassword);
if ((src.Length != 0x31) || (src[0] != 0))
{
return false;
}
byte[] dst = new byte[0x10];
Buffer.BlockCopy(src, 1, dst, 0, 0x10);
byte[] buffer3 = new byte[0x20];
Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20);
using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, dst, 0x3e8))
{
buffer4 = bytes.GetBytes(0x20);
}
return ByteArraysEqual(buffer3, buffer4);
}
So my question really is, Is sending the username and passwords in this way secure enough? As everything is going over https I am assuming it is but would like some guidance as I am fairly new to security in general.
The service will also be IP restricted.
Here is my service model config.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehaviour">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyValidatorClass,MyNameSpace" />
</serviceCredentials>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="HttpBinding" maxReceivedMessageSize="2097152" receiveTimeout="00:02:00" sendTimeout="00:02:00">
</binding>
<binding name="HttpsBinding" maxReceivedMessageSize="2097152" receiveTimeout="00:02:00" sendTimeout="00:02:00">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="MyService" behaviorConfiguration="MyServiceBehaviour">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="HttpsBinding" contract="MyContract" />
<host>
<baseAddresses>
<add baseAddress="https://MyServiceInAzure.net/" />
</baseAddresses>
</host>
</service>
</services>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
And here is what the clients will be using:
Client.Service call = new Client.ServiceClient();
call.ClientCredentials.UserName.UserName = "MyUsername";
call.ClientCredentials.UserName.Password = "MyPassword";
var result = call.PostCall("Hello World");
Thanks