How to Store and Retrieve Credentials on Windows Using C#

How to store and retrieve credentials on Windows using C#

You can use the Windows Credential Management API. This way you will ask the user for the password only once and then store the password in Windows Credentials Manager.

Next time your application starts and it needs to use the password it will read it from Windows Credentials Manager. One can use the Windows Credential Management API directly using P/Invoke (credwrite, CredRead, example here) or via a C# wrapper CredentialManagement.


Sample usage using the NuGet CredentialManagement package:

public class PasswordRepository
{
private const string PasswordName = "ServerPassword";

public void SavePassword(string password)
{
using (var cred = new Credential())
{
cred.Password = password;
cred.Target = PasswordName;
cred.Type = CredentialType.Generic;
cred.PersistanceType = PersistanceType.LocalComputer;
cred.Save();
}
}

public string GetPassword()
{
using (var cred = new Credential())
{
cred.Target = PasswordName;
cred.Load();
return cred.Password;
}
}
}

I don't recommend storing passwords in files on client machines. Even if you encrypt the password, you will probably embed the decryption key in the application code which is not a good idea.

Retrieve credentials from Windows Credentials Store using C#

There is a NuGet library that I've been using, called CredentialManagement.

The usage is pretty simple. I wrapped it a little, but I probably didn't need to:

public static class CredentialUtil
{
public static UserPass GetCredential(string target)
{
var cm = new Credential {Target = target};
if (!cm.Load())
{
return null;
}

// UserPass is just a class with two string properties for user and pass
return new UserPass(cm.Username, cm.Password);
}

public static bool SetCredentials(
string target, string username, string password, PersistanceType persistenceType)
{
return new Credential {Target = target,
Username = username,
Password = password,
PersistanceType = persistenceType}.Save();
}

public static bool RemoveCredentials(string target)
{
return new Credential { Target = target }.Delete();
}
}

Sample usage:

CredentialUtil.SetCredentials("FOO", "john", "1234", PersistanceType.LocalComputer);
var userpass = CredentialUtil.GetCredential("FOO");
Console.WriteLine($"User: {userpass.Username} Password: {userpass.Password}");
CredentialUtil.RemoveCredentials("FOO");
Debug.Assert(CredentialUtil.GetCredential("FOO") == null);

If you're interested in implementing it yourself, browse the source:
http://credentialmanagement.codeplex.com/SourceControl/latest

The trick is that there is no C# API into the Credential Manager. This library wraps the other .dll entry points nicely. :-)

.NET Core: How to access Windows Credential Manager if running on Windows (otherwise ignore)?

I ended up using the Data Protection API for Windows (DPAPI) to store secrets in a file that is encrypted within the scope of the logged in user.

Encrypted storage of a password:

try
{
var passwordBytes = Encoding.UTF8.GetBytes(password);
var protectedPasswordBytes = ProtectedData.Protect(passwordBytes, null, DataProtectionScope.CurrentUser);
var protectedPasswordBytesBase64 = Convert.ToBase64String(protectedPasswordBytes);
File.WriteAllText(passwordFilePath, protectedPasswordBytesBase64);
} catch (PlatformNotSupportedException)
{
Debug.WriteLine("Could not store credentials");
}

Decryption:

if (File.Exists(passwordFilePath))
{
var protectedPasswordBytesBase64 = File.ReadAllText(passwordFilePath);
var protectedPasswordBytes = Convert.FromBase64String(protectedPasswordBytesBase64);
var passwordBytes = ProtectedData.Unprotect(protectedPasswordBytes, null, DataProtectionScope.CurrentUser);
password = Encoding.UTF8.GetString(passwordBytes);
}

(Only works on Windows, for other OSes I'll use other solutions.)

Access Windows Credentials in Credential Manager

There is a Nuget library called CredentialManagement http://nuget.org/packages/CredentialManagement/
from the answer here: Retrieve Credentials from Windows Credentials Store using C#

works perfectly

        var cm = new Credential();
cm.Target = "mycredentialname";

if (!cm.Exists())
{
Console.WriteLine("cm is null");
}
cm.Load();
Console.WriteLine("Password: " + cm.Password);
Console.WriteLine("Username: " + cm.Username);

Retrieve Credentials from Windows generic Credentials Store using C# in ASP.net website under IIS

You should switch "Load User Profile" parameter of IIS App Pool to true. Then your code should start working.

How to save an email/password combination for windows program?

Uhm... Don't store in AppConfig settings.

If you cannot use a database for that (storing hashed and encrypted strings) get a new file for that, you can even protect it to allow only the service user account to read/modify it, or store it on the service profile directory (its user account profile directory)

I would do it using an ini file structure more easy to read than an xml, where each line contains something like

var mergedCredential = string.Format("{0}|{1}", "user@here.com" , "P@ssw0rd");
User1HashedCredentials=EncryptString("new username", mergedCredential);

I used a pipe to "merge" the credential as you can prevent users to use it on username

When you decrypt you split by "|"

var credentials = DecryptString("new username", User1HashedCredentials);
var splitted = credentials.Split('|');
Username = splitted[0]
Password = splitted[1]

An example of ini file:

[Users]

Count=5

[SendEmailSection]

User1=dsaa$#asdasd$#@rr==

User2=dggggjh7/sd$#@rr==

User3=dsaasd"/$%asdasd$#@rr==

User4=dsas/&"dasd$#@rr==

User5=dsAa&s3dasd$#@rr==

Which is easier to mantain and modify. You can even make your own specialized ini reader/writer Read sections, split by "="



Related Topics



Leave a reply



Submit