Using the Credential Management API

Wrapper Code

Following secure development best practice, an application should obtain and store user credentials securely. Microsoft has provided a means to accomplish this on the desktop: the unmanaged Credential Management API, which exposes the capability to provide a standard login experience for the user which is also secure. There are a number of benefits to utilising this:

The code is maintained by Microsoft. I put this in the first because I think it is an important advantage.

The user experience is consistent.

The user credentials can be shared easily across applications.

It's secure. It's well-tested as being secure. If a security flaw is discovered, you can be sure that Microsoft will fix it.

What I didn't find was a comprehensive code sample of a Generic dialog implementation, so I decided to put one together.

Before going any further, I should highlight that the Credential Management API is only available on Windows XP / Windows Server 2003 onwards.

I don't usually post such a large slice of code as this but I felt that it would be the clearest way to describe the class and also has the benefit that readers can cut & paste the entire sample easily. So here is my entire credential wrapper code:

/// <summary>Initializes a new instance of the <see cref="T:SecureCredentialsLibrary.CredentialsDialog"/> class
/// with the specified target.</summary>
/// <param name="target">The name of the target for the credentials, typically a server name.</param>
public CredentialsDialog(string target) : this(target, null)
{ }
/// <summary>Initializes a new instance of the <see cref="T:SecureCredentialsLibrary.CredentialsDialog"/> class
/// with the specified target and caption.</summary>
/// <param name="target">The name of the target for the credentials, typically a server name.</param>
/// <param name="caption">The caption of the dialog (null will cause a system default title to be used).</param>
public CredentialsDialog(string target, string caption) : this(target, caption, null)
{ }
/// <summary>Initializes a new instance of the <see cref="T:SecureCredentialsLibrary.CredentialsDialog"/> class
/// with the specified target, caption and message.</summary>
/// <param name="target">The name of the target for the credentials, typically a server name.</param>
/// <param name="caption">The caption of the dialog (null will cause a system default title to be used).</param>
/// <param name="message">The message of the dialog (null will cause a system default message to be used).</param>
public CredentialsDialog(string target, string caption, string message) : this(target, caption, message, null)
{ }
/// <summary>Initializes a new instance of the <see cref="T:SecureCredentialsLibrary.CredentialsDialog"/> class
/// with the specified target, caption, message and banner.</summary>
/// <param name="target">The name of the target for the credentials, typically a server name.</param>
/// <param name="caption">The caption of the dialog (null will cause a system default title to be used).</param>
/// <param name="message">The message of the dialog (null will cause a system default message to be used).</param>
/// <param name="banner">The image to display on the dialog (null will cause a system default image to be used).</param>
public CredentialsDialog(string target, string caption, string message, Image banner)
{
this.Target = target;
this.Caption = caption;
this.Message = message;
this.Banner = banner;
}

private bool _alwaysDisplay = false;
/// <summary>
/// Gets or sets if the dialog will be shown even if the credentials
/// can be returned from an existing credential in the credential manager.
/// </summary>
public bool AlwaysDisplay
{
get
{
return _alwaysDisplay;
}
set
{
_alwaysDisplay = value;
}
}

/// <summary>Returns a DialogResult indicating the user action.</summary>
/// <param name="owner">The System.Windows.Forms.IWin32Window the dialog will display in front of.</param>
/// <remarks>
/// Sets the name, password and SaveChecked accessors to the state of the dialog as it was dismissed by the user.
/// </remarks>
private DialogResult ShowDialog(IWin32Window owner)
{
// set the api call parameters
StringBuilder name = new StringBuilder(CREDUI.MAX_USERNAME_LENGTH);
name.Append(this.Name);

by lina20 (0 replies)

by tufffta (0 replies)

Published 3 years ago, running time 0h56m

While at CodeMash, Carl and Richard collected some great stories. First up is Evan Huack, who digs into cudafy, a library on codeplex that allows you to run C# code (any IL code actually) on your GPU. The second story is about Jessie Shternshus and her company The Improv Effect. Jessie talks abou.