How to prompt for a password on Windows?

  • .NET
  • Security

This post is part of the series 'Password management'. Be sure to check out the rest of the blog posts of the series!

In the previous post, we discovered how to store a password on Windows using the Credential Manager. Today, we'll see the other part of the API with allows the user to enter their password. This API allows asking for a username/password for a console application or a GUI application. Optionally, they can save the password in the Credential Manager, so the next time the passwords are read directly from the Credential Manager instead of prompting the user.

Credential Manager GUI

Console application

Asking for a password in a console application is not easy. It requires to mask the data when the user enters it. It means you have to intercept keys using Console.ReadKey and handle it correctly. Or you can use the function CredUICmdLinePromptForCredentials.

Instead of writing your own wrapper, you can use the NuGet package Meziantou.Framework.Win32.CredentialManager (NuGet, GitHub)

// Requires NuGet Meziantou.Framework.Win32.CredentialManager
using System;
using Meziantou.Framework.Win32;

internal class Program
{
    private static void Main(string[] args)
    {
        var creds = CredentialManager.PromptForCredentialsConsole(target: "https://www.meziantou.net");

        Console.WriteLine($"User: {creds?.UserName}, Password: {creds?.Password}, Domain: {creds?.Domain}");
    }
}

You can set an optional username, so the user will only have to enter their password.

// Requires NuGet Meziantou.Framework.Win32.CredentialManager
using System;

internal class Program
{
    private static void Main(string[] args)
    {
        var creds = CredentialManager.PromptForCredentialsConsole(
            target: "https://www.meziantou.net",
            saveCredential: CredentialSaveOption.Hidden,
            userName: "Meziantou"
            );

        Console.WriteLine($"User: {creds?.UserName}, Password: {creds?.Password}, Domain: {creds?.Domain}");
    }
}

PromptForCredentialsConsole result

Desktop application

In a desktop application, you can use a PasswordBox to ask for the user to enter their password. However, you have to design the login window for your application. The Credential Manager comes with a default UI that allows you to prompt for credentials: CredUIPromptForWindowsCredentials.

Instead of writing your own wrapper, you can use the NuGet package Meziantou.Framework.Win32.CredentialManager (NuGet, GitHub)

// Requires NuGet Meziantou.Framework.Win32.CredentialManager
using System;

internal class Program
{
    private static void Main(string[] args)
    {
        var creds = CredentialManager.PromptForCredentials(
                target: "https://www.meziantou.net",
                captionText: "https://www.meziantou.net",
                messageText: "This will allow SampleApp to authenticate to Meziantou's blog",
                saveCredential: CredentialSaveOption.Selected
                //userName: "Meziantou" // Pre-fill the UI with a default username
                );

        Console.WriteLine($"User: {creds?.UserName}, Password: {creds?.Password}, Domain: {creds?.Domain}");
    }
}

Credential Manager GUI

UWP application

UWP comes with its own wrapper of the Credential Manager API. So, you don't need any code nor third-party libraries to use it. It's available through the CredentialPicker class:

<Page
    x:Class="SampleCredentialPicker.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Button Click="Button_Click">Login</Button>
    </Grid>
</Page>
using System;
using Windows.Security.Credentials.UI;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace SampleCredentialPicker
{
    public sealed partial class MainPage : Page
    {
        public MainPage() => InitializeComponent();

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            var options = new CredentialPickerOptions()
            {
                TargetName = "https://www.meziantou.net",
                Caption = "https://www.meziantou.net",
                Message = "This will allow SampleApp to authenticate to Meziantou's blog",
                CredentialSaveOption = CredentialSaveOption.Selected,
                AuthenticationProtocol = AuthenticationProtocol.Basic, // Allows to get the clear password
            };

            CredentialPickerResults result = await CredentialPicker.PickAsync(options);

            var dialog = new MessageDialog($"User: {result.CredentialUserName}, Password: {result.CredentialPassword}, Domain: {result.CredentialDomainName}");
            await dialog.ShowAsync();
        }
    }
}

UWP - CredentialPicker

Follow me:
Enjoy this blog?Buy Me A CoffeeDonate with PayPal

Leave a reply