Storing User Credentials Securely in Windows Store Apps – Boredom Challenge Day 17

Standard

It is quite common to need to store our users’ usernames and passwords (or other critical information, such as access tokens) in our apps, so our users won’t have to sign in each time they use the app. However, although I’ve said this is commonly needed, we need to be careful when storing them because we can’t afford even a slightest chance of them being exposed.

So we're talking about "Remember me" or "Keep me signed in" functionality.

So we’re talking about “Remember me” or “Keep me signed in” functionality.

In Windows Store apps, there is a small but potentially deadly pitfall when implementing this feature: Using application local settings for storing username and password. Application settings may be kept isolated from other apps and users but that isn’t enough. They are kept in the registry, and if you dig deep enough and know what you are doing, you may find a way to read them (check this link for starters). For example, in my previous blog posts where we integrated Facebook, we kept the user’s access token this way (for simplicity, of course), and if anyone were to read the application settings and find that token they could read our user’s timeline and/or post stuff on his/her behalf.

This is what will happen when your Facebook access token is exposed, at best.

This is what will happen when your Facebook access token is exposed, at best.

Anyway, joking aside, the correct way to store critical information in Windows Store Apps is to use credential lockers; namely, the PasswordVault and PasswordCredential classes under Windows.Security.Credentials workspace, and in this article we’ll make an example app that keeps the user’s username and password securely.

We’ll create an app with a simple login screen that asks for the user’s username and password, along with a “Remember me” option. We’ll also add a logout feature to see how we’ll remove the existing user information. We’ll start with a blank Windows Store App project.

3

Then we’ll make the login interface in MainPage.xaml:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel x:Name="StackPanelLogin" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center" Width="300">
            <TextBlock FontSize="15" FontFamily="Segoe UI" FontWeight="Light" Text="Username:"/>
            <TextBox x:Name="TextBoxUserName" Margin="0,5,0,0"/>
            <TextBlock FontSize="15" FontFamily="Segoe UI" FontWeight="Light" Text="Password:" Margin="0,10,0,0"/>
            <PasswordBox x:Name="PasswordBox" Margin="0,5,0,0"/>
            <CheckBox x:Name="CheckBoxRememberMe" Content="Remember Me" VerticalAlignment="Stretch" Margin="0,5,0,0"/>
            <Button x:Name="ButtonSignIn" Content="Sign In" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,5,0,0" Click="ButtonSignIn_Click"/>
        </StackPanel>
        <TextBlock x:Name="TextBlockWelcome" FontSize="15" FontFamily="Segoe UI" FontWeight="Light" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,60" Visibility="Collapsed"/>
        <Button x:Name="ButtonSignOut" Content="Sign Out" HorizontalAlignment="Center" Margin="0,30,0,0" VerticalAlignment="Center" Visibility="Collapsed" Click="ButtonSignOut_Click"/>
    </Grid>

Now, we will create our PasswordVault object and also set the correct username and password for this example in App.xaml.cs. Normally, when we get the user’s username and password we’ll be checking it in our own database but for this example they will just be static string values.

using Windows.Security.Credentials;
        public PasswordVault vault = new PasswordVault();

        public static string correctUsername = "encephalon";
        public static string correctPassword = "password123";

Now, we will do the saving and deleting parts in the Click events of sign in and sign out buttons:

using Windows.UI.Popups;
using Windows.Security.Credentials;
        async private void ButtonSignIn_Click(object sender, RoutedEventArgs e)
        {
            if (TextBoxUserName.Text == App.correctUsername && PasswordBox.Password == App.correctPassword)
            {
                if (CheckBoxRememberMe.IsChecked == true)
                {
                    ((App)Application.Current).passwordVault.Add(new PasswordCredential("User Credentials", TextBoxUserName.Text, PasswordBox.Password));
                }
                TextBlockWelcome.Text = String.Format("Welcome {0}!", TextBoxUserName.Text);
                StackPanelLogin.Visibility = Visibility.Collapsed;
                TextBlockWelcome.Visibility = Visibility.Visible;
                ButtonSignOut.Visibility = Visibility.Visible;
                TextBoxUserName.Text = String.Empty;
                PasswordBox.Password = String.Empty;
            }
            else
            {
                MessageDialog messageDialog = new MessageDialog("Wrong username or password.");
                await messageDialog.ShowAsync();
            }
        }

        private void ButtonSignOut_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                PasswordCredential signedInUser = ((App)Application.Current).passwordVault.FindAllByResource("User Credentials").FirstOrDefault();
                if (signedInUser != null)
                {
                    ((App)Application.Current).passwordVault.Remove(signedInUser);
                }
            }
            catch
            {
                //The user didn't choose "Remember me" while signing in so the password vault is empty, don't crash and move on
            }
            TextBlockWelcome.Visibility = Visibility.Collapsed;
            ButtonSignOut.Visibility = Visibility.Collapsed;
            StackPanelLogin.Visibility = Visibility.Visible;
            TextBlockWelcome.Text = String.Empty;
        }

You see that we checked if the username and password is correct, and if they are, we added them to the password vault if the user also chose to remember them. You will also notice that when signing out, we reached the user’s username and password via the FirstOrDefault() method, which selected the first user credential. This is because we only keep one user’s credentials at the same time. If you intend to do something like this for several users, you would then need to also keep a list of usernames and reach them via calling “PasswordVault.Retrieve(“User Credentials”, username)”. Anyway, the last thing we need to do is to check if a user wanted us to remember him/her and sign in automatically:

        async void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                PasswordCredential signedInUser = ((App)Application.Current).passwordVault.FindAllByResource("User Credentials").FirstOrDefault();
                signedInUser.RetrievePassword();
                if (signedInUser != null)
                {
                    if (signedInUser.UserName == App.correctUsername && signedInUser.Password == App.correctPassword)
                    {
                        TextBlockWelcome.Text = String.Format("Welcome {0}!", signedInUser.UserName);
                        StackPanelLogin.Visibility = Visibility.Collapsed;
                        TextBlockWelcome.Visibility = Visibility.Visible;
                        ButtonSignOut.Visibility = Visibility.Visible;
                        TextBoxUserName.Text = String.Empty;
                        PasswordBox.Password = String.Empty;
                    }
                    else
                    {
                        ((App)Application.Current).passwordVault.Remove(signedInUser);
                        MessageDialog messageDialog = new MessageDialog("Your stored username - password combination is no longer valid. Please sign in again.");
                        await messageDialog.ShowAsync();
                    }
                }
            }
            catch
            {
                //There aren't any saved credentials, don't crash and move on
            }
        }

Here, we checked if we have any saved user credentials and if they are still valid (maybe the user changed the password somewhere else, or maybe this user’s account is deleted from the system). If they are, we sign in automatically. Notice that we have to explicitly call PasswordCredential.RetrievePassword() to get the password, otherwise we’ll get an empty string.

Alright then, let’s run the app and sign in. After signing in, close the app and run it again. If you checked remember me previously, you won’t need to sign in again. 🙂

4

5

And this is how we can keep our users’ credentials secure in Windows Store apps. 🙂

Here‘s our example’s source code.

Thank you for reading.

Advertisement

Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s