.NET Zone is brought to you in partnership with:

Den is a DZone Zone Leader and has posted 460 posts at DZone. You can read more from them at their website. View Full User Profile

Authentication with Windows Azure Mobile Services on Windows Phone

04.25.2013
| 3001 views |
  • submit to reddit

Despite its fairly simple wrapper, Azure Mobile Services can be used for standard in-app authentication. In this article I am going over a basic implementation with hash-based credentials validation.

At this point, make sure that you downloaded and added a reference to the Azure Mobile Services SDK for Windows Phone 8 (or you could you the pre-release of the SDK for Windows Phone 7.5). NuGet is the easiest way to do that.

Begin by creating a new table in your Azure management portal - Users.

In the App class, include a reference to the MobileServiceClient instance that you will be using to connect to the underlying database:

public static MobileServiceClient MobileService = new MobileServiceClient(
    "https://YOUR_AZURE_MS.azure-mobile.net/",
    "KEY"
);

Now let's think about the logistics of the security mechanisms. Each password is hashed and salted. It is later stored in the Users table. At this point you might be thinking - the hash is stored with the salt in the same table, isn't that a security risk? Not really, as long as the password that is stored is in an unrecorverable form - there is no way to get it back, even if both the hash and the salt are somehow retrieved. Also, the salt is assumed to be unique for each password. This helps protect the system against dictionary attacks.

Here is how the password hash is generated:

public static byte[] GenerateHash(string password, byte[] salt)
{            
    byte[] passwordData = Encoding.UTF8.GetBytes(password);

    byte[] composite = new byte[passwordData.Length + 32];

    Array.Copy(passwordData, composite, passwordData.Length);
    Array.Copy(salt, 0, composite, passwordData.Length, salt.Length);

    SHA256 hashFunction = new SHA256Managed();
    byte[] hash = hashFunction.ComputeHash(composite);

    return hash;
}

The salt is passed to the function as a byte array that is later appended to the password. SHA256 is used to compute the core hash - avoid using hash algorithms such as MD5 and SHA1.

The hash is generated through a cryptographically secure random number generator - RNGCryptoServiceProvider.

public static byte[] GetSalt()
{
    byte[] rngContainer = new byte[32];
    RNGCryptoServiceProvider rngProvider = new RNGCryptoServiceProvider();
    rngProvider.GetBytes(rngContainer);

    return rngContainer;
}

Internally, I will also need to retrieve the byte representation from the salt string for validation purposes. Here is what the function looks like:

public static byte[] GetSaltFromString(string source)
{
    string[] raw = source.Split('-');
    byte[] result = new byte[raw.Length];
    for (int i = 0; i < raw.Length; i++)
    {
        result[i] = Convert.ToByte(raw[i], 16);
    }
    return result;
}

To send data to Azure, we need a serializable user model, as well as the ability for the developer to make the choice whether a new random hash should be used or not:

public static User GetSecureUserModel(string username, string password, string email = "", 
    byte[] customSalt = null)
{
    User user = new User();
    user.Username = username;
    user.Email = email;

    byte[] hash;
    if (customSalt == null)
    {
        byte[] salt = HashHelper.GetSalt();
        user.Salt = BitConverter.ToString(salt);

        hash = HashHelper.GenerateHash(password, salt);

    }
    else
    {
        hash = HashHelper.GenerateHash(password, customSalt);
    }

    user.Hash = BitConverter.ToString(hash);

    return user;
}

You can infer the model structure from the table fields:

[DataTable(Name="Users")]
public class User
{
    public int? Id { get; set; }
    public string Username { get; set; }
    public string Salt { get; set; }
    public string Hash { get; set; }
    public string Email { get; set; }
}

On registration, a table insertion is executed:

public async static Task<bool> RegisterUser(User user)
{
    IMobileServiceTable<User> userTable = App.MobileService.GetTable<User>();
    List<User> userList = await userTable.Take(1).Where(x => x.Username == user.Username).ToListAsync();
    if (userList.Count == 0)
    {
        await App.MobileService.GetTable<User>().InsertAsync(user);
        return true;
    }
    else
    {
        return false;
    }
}

Here is what we do when we need to validate credentials that are given the user - a new user model is obtained based on the input and the hash for the given username is retrieved from the database:

public static async Task<User> GetUserFromDatabase(string username)
{
    IMobileServiceTable<User> userTable = App.MobileService.GetTable<User>();
    List<User> userList = await userTable.Take(1).Where(x => x.Username == username).ToListAsync();

    if (userList.Count == 0)
        return null;
    else
        return userList.First();
}

The login is verified against the existing model, with the existing salt being used to create a new password hash, based on the new input.

public async static Task<User> VerifyLogin(string username, string password)
{
    User dbUser = await GetUserFromDatabase(username);

    if (dbUser != null)
    {
        User localUser = GetSecureUserModel(username, password, "", 
            HashHelper.GetSaltFromString(dbUser.Salt));
        if (dbUser.Hash == localUser.Hash)
            return dbUser;
    }

    return null;
}

This model can be applied to simple mobile applications that need a core authentication system.
There are several additions that can be added to the implementation - for example, additional hashing can be added to on the server side. A more complex hashing algorithm can be also used with more variation added to the salt.