Introduction
Recently, I came across a situation where I needed to provide the same authentication service provided by the ASP.NET Roles and Membership provider, but on a mobile device. A mobile device would sync to a backend database, pulling down all the aspNet_XXXX tables. The user of the mobile device would then be able to validate their account against the mobile device using their existing ASP.NET Roles and Membership credentials.
Using the code
The code below first demonstrates checking for a username match, and then comparing the password hash originally generated by the user to the hash created with the password they have supplied the program.
In the last lines of the program, I persist the user data so that it is available to the rest of the program.
public bool LogonUser(string userName, string passWord)
{
Guid userID = Guid.Empty;
string originalHash = "";
string saltValue = "";
DataLayer dataLayer = new DataLayer();
try
{
string SQL =
" Select aspnet_Membership.UserId, "
+ " Password, "
+ " PasswordSalt "
+ " From aspnet_Membership inner join "
+ " aspnet_Users on aspnet_Membership.UserID"
+ " = aspnet_Users.UserID "
+ " Where LoweredUserName = @p1 ";
SqlCeCommand sqlCeCommand = new SqlCeCommand(SQL,
dataLayer.GetOpenConnection);
SqlCeParameter param1 =
sqlCeCommand.Parameters.Add("p1",
System.Data.SqlDbType.NVarChar);
param1.Value = userName.ToLower();
SqlCeDataReader reader = sqlCeCommand.ExecuteReader();
while (reader.Read())
{
userID = reader.GetGuid(0);
originalHash = reader.GetString(1);
saltValue = reader.GetString(2);
break;
}
reader.Close();
}
catch (Exception ex)
{
new Logger().Log(ex);
throw ex;
}
finally
{
dataLayer.CloseSQLConnection();
}
if (userID.CompareTo(Guid.Empty) != 0)
{
byte[] bIn = Encoding.Unicode.GetBytes(passWord);
byte[] bSalt = Convert.FromBase64String(saltValue);
byte[] bAll = new byte[bSalt.Length + bIn.Length];
byte[] bRet = null;
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
HashAlgorithm s = HashAlgorithm.Create("SHA1");
bRet = s.ComputeHash(bAll);
string newHash = Convert.ToBase64String(bRet);
if (originalHash != newHash)
throw new Exception("Incorrect Username/Password" +
" combination. Please try again");
}
else
{
throw new Exception("Incorrect Username/Password" +
" combination. Please try again");
}
Config.UserID = userID;
Config.UserName = userName;
Config.PassWord = passWord;
return true;
}
It took me a while to get this, so hopefully, this will save someone else scratching their head!