How to store and retrieve credentials on Windows using C#
Asked Answered
S

1

23

I build a C# program, to be run on Windows 10. I want to send emails from this program (calculation results) by just pressing a button. I put the from: e-mail address and the subject:, etc. in C# properties, but I do not want to put a clear text password anywhere in the program, AND I don't want the user to have to type in the password for the server each time a mail is sent.

Can that be done?

If so, how (generally)?

I was thinking of putting all that e-mail information, including an encrypted password for the server in a data file to be read during startup of the program.

Or maybe Windows 10 has a facility for that...

Superabound answered 13/9, 2015 at 10:30 Comment(1)
Possible duplicate of Retrieve credentials from Windows Credentials Store using C#Unworthy
P
39

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.

Plascencia answered 13/9, 2015 at 14:28 Comment(1)
The package CredentialManagement is not updated since 2014. It may throw a compilation error "Assembly generation failed -- Referenced assembly 'CredentialManagement' does not have a strong name." when you require (strong) assembly signing.Mussorgsky

© 2022 - 2024 — McMap. All rights reserved.