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 explored how to store a password on Windows using the Credential Manager. Today, we cover the complementary part of the API: prompting the user to enter their credentials. This API supports prompting for a username and password in both console and GUI applications. Optionally, users can save their credentials in the Credential Manager so that subsequent requests read from it directly instead of prompting again.
Credential Manager GUI demo
#Console application
Asking for a password in a console application is not trivial. You must mask the input as the user types, which means intercepting keys with Console.ReadKey and handling them correctly. Alternatively, you can use the CredUICmdLinePromptForCredentials function.
Instead of writing your own wrapper, you can use the NuGet package Meziantou.Framework.Win32.CredentialManager (NuGet, GitHub)
C#
// 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 pre-fill an optional username so the user only needs to enter their password.
C#
// 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 demo
#Desktop application
In a desktop application, you can use a PasswordBox to collect the user's password. However, this requires designing a custom login window. The Credential Manager provides a built-in UI for prompting credentials via CredUIPromptForWindowsCredentials.
Instead of writing your own wrapper, you can use the NuGet package Meziantou.Framework.Win32.CredentialManager (NuGet, GitHub)
C#
// 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 demo
#UWP application
UWP includes a built-in wrapper for the Credential Manager API, so no additional code or third-party libraries are needed. It is available through the CredentialPicker class:
XAML
<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>
C#
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
Do you have a question or a suggestion about this post? Contact me!