Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Authentication with Windows Azure Mobile Services on Windows Phone

DZone's Guide to

Authentication with Windows Azure Mobile Services on Windows Phone

· Mobile Zone
Free Resource

Discover how to focus on operators for Reactive Programming and how they are essential to react to data in your application.  Brought to you in partnership with Wakanda

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.

Learn how divergent branches can appear in your repository and how to better understand why they are called “branches".  Brought to you in partnership with Wakanda

Topics:

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}