A little while ago I wrote an article on Managing Secrets In Linux which covered some of the tools available to manage secrets on a Linux system. I wanted to follow that up by exploring similar techniques for managing secrets on Windows. In researching this piece I found that in all of the articles I found some of the guidance, including a key detail they all refer to, is outdated. So this is my spin on the subject, where I’ll address the issue with the other articles I have found, acknowledge their great work and walk you step by step through managing secrets on Windows.
Introducing Credential Manager
Starting from the top; Windows has a built-in tool called Credential Manager that was first introduced with Windows 7. Credential Manager is a tool that stores your credentials, such as usernames and passwords, in a secure location on your computer. You can use Credential Manager to store credentials for websites, network locations, and applications. Credential Manager can be a useful tool for managing your passwords and other sensitive information.
Microsoft’s own documentation on Credential Manager that you can find online is surprisingly limited! Fortunately, however, a wide range of sources such as Windows OS Hub do a much better job of discussing the tool (caution: this article is victim of the “gotcha” that I’ll discuss below).
You can find Credential Manager by searching for it in the Start menu or by going to Control Panel > User Accounts > Credential Manager.
The Different Credential Types
Credential Manager can store three different types of credentials:
- Windows Credentials: These are credentials that are used to log in to services that support Windows authentication such as Remote Desktop connections, network shares, and websites that use Windows authentication.
- Certificate-Based Credentials: These are credentials that are used to authenticate with websites and services that require a certificate for authentication. Certificates are sourced from the Personal directory of the Windows Certificate Store.
- Generic Credentials: These are credentials that are used to log in to websites and services that do not support Windows authentication or certificate-based authentication. Generic credentials can be used to store any type of credential, such as usernames and passwords for websites, network shares, and applications.
Mostly in this article I’ll be working with Generic credentials but the same principles apply to the other types as well.
Working With Credentials In The GUI
Before we get to the command line magic let’s quickly talk about using the GUI; this is Windows after all and if it didn’t have the “windows” then it might as well be Linux, right(?)! The Credential Manager GUI is pretty straightforward to use. You can add, edit, and remove credentials from the Credential Manager as follows:
Adding Credentials In The GUI
- Open Credential Manager by searching for it in the Start menu or by going to Control Panel > User Accounts > Credential Manager.
- Click on “Add a Windows credential” or “Add a generic credential” depending on the type of credential you want to add. We’ll be adding a generic credential in this example.
- Enter the name of the server or website you want to store the credentials for in the “Internet or network address” field. This field can also be used as a friendly name for the credential if you’re not going to be using it for a network address. We’ll use it for a friendly name in this example.
- Enter your username and password in the “User name” and “Password” fields respectively.
Editing Credentials In The GUI
- Open Credential Manager by searching for it in the Start menu or by going to Control Panel > User Accounts > Credential Manager.
- Click on the credential you want to edit and expand it by clicking on the down arrow next to it.
- Click on “Edit” to edit the credential.
- Make your changes and click “Save”.
Removing Credentials In The GUI
- Open Credential Manager by searching for it in the Start menu or by going to Control Panel > User Accounts > Credential Manager.
- Click on the credential you want to remove and expand it by clicking on the down arrow next to it.
- Click on “Remove” to remove the credential.
Working With Credentials On The Command Line
OK! On with the “fun stuff”, let’s get to the command line! There are tools of varying capability across both PowerShell and the Command Prompt (cmd
), and we’ll have a look at both. Let’s start with PowerShell as the more modern and capable of the two.
PowerShell Credential Manager Tools
PowerShell, both Windows Powershell (<=v5.x) and modern, cross-platform PowerShell (6 and 7 at the time of writing) can be extended with an installable module called CredentialManager
that provides a set of cmdlets for working with the Credential Manager. But… we need to talk about the gotcha first.
The PowerShell Credential Manager Gotcha
Articles like the one we saw earlier from Windows OS Hub or this one from DelftStack all refer to a module called CredentialManager
that you can install from the PowerShell Gallery using the cmdlet Install-Module -Name CredentialManager
. The problem is that this module was archived back in September 2021 and is no longer maintained (see the GitHub repository). While it worked for a while more recent releases of PowerShell, particular in the cross-platform PowerShell 7 family seem to have broken compatibility with the module.
Where this will become evident is when you try to add a credential with the New-StoredCredential
cmdlet. You’ll get an error message like this:
New-StoredCredential: Argument 'New-StoredCredential' is not recognized as a cmdlet: Could not load type 'System.Web.Security.Membership' from assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
Fortunately the project was forked and an updated version released here and its GitHub here. This means that with a minor adjustment to the installation command you can still use the module’s cmdlets. The new command is Install-Module -Name TUN.CredentialManager
.
After installing this version all of the cmdlets are the same as the original module, so you can follow the guidance in the articles I linked to earlier with the updated module. Of course, I’ll save you going to those articles and provide the guidance here…
Installing The PowerShell Credential Manager Module
To install the updated version of the CredentialManager
module, open PowerShell and run the following command:
Install-Module -Name TUN.CredentialManager
In the example above I added a couple of extra switches to the Install-Module
cmdlet. The -Force
switch is used to force the installation of the module without prompting for confirmation. The -AllowClobber
switch is used to allow the module to overwrite any existing modules with the same name. This is useful if you have an older version of the module installed and you want to update it to the latest version, and -Verbose
is used to provide more detailed output about the installation process.
Importing The PowerShell Credential Manager Module
Once the module is installed you can import it into your PowerShell session with the following command:
Import-Module -Name TUN.CredentialManager
Also note that immediately after install some versions of PowerShell have had an issue where the module is not imported automatically. If you find that the module is not available after installation you can import it manually with the command above.
Adding Credentials In PowerShell
Let’s start with a simple example to get started; side note, please do not use this example outside of practice. I hope it goes without saying but entering your password in plain text in a script or on the command line is a bad idea. That said, here’s how you can add a credential in PowerShell:
New-StoredCredential -Target 'MyCredential' -UserName 'MyUsername' -Password 'MyPassword'
Once we’ve done this we can check in Credential Manager to see that the credential has been added:
But remember, this is a bad idea! So let’s look at a better way to do this…
We can use the Get-Credential
cmdlet to prompt for a username and password and store the credential in a variable. Here’s an example:
Get-Credential -Message 'Enter your credentials' -UserName 'MyUsername' | New-StoredCredential -Target 'MyCredential
Depending on the version of PowerShell you are using it may either prompt you for the password in the CLI or it may pop a dialog box up for you to enter the password. Either way, the password is not stored in plain text in the script.
As we can see this stored in the response to the cmdlet.
As you can see the password is not displayed in plain text whilst the credential is being added.
We can see both credentials in Credential Manager regardless of how they were added.
If you’re sharp-eyed you may have noticed a difference in the way the password is stored between the two methods. In the first, where we used the -Password
switch, the password is stored in plain text. In the second, where we used Get-Credential
, the password is stored as a SecurePassword
object. When we retrieve the credential we’ll see that this will make a difference in what is displayed.
If we wanted to store the password securely without needing to prompt the user, for example if we are creating the password programmatically, we can use the ConvertTo-SecureString
cmdlet to convert the password to a secure string. Here’s an example:
$Password = 'MyPassword' | ConvertTo-SecureString -AsPlainText -Force # Obviously we're passing the value in plain text here but you could use a variable or other method to pass the password
New-StoredCredential -Target 'MyCredential' -UserName 'MyUsername' -SecurePassword $Password -Persist LocalMachine
Or we could prompt the user another way using the Read-Host
cmdlet:
$Password = Read-Host -Prompt 'Enter your password' -AsSecureString
New-StoredCredential -Target 'MyCredential' -UserName 'MyUsername' -SecurePassword $Password -Persist LocalMachine
Credential Persistence
One thing to note is that credentials added in this way can have different levels of persistence. The eagle-eyed amongst you may have spotted that I specified a -Persist
switch in the second credential I added above (see the pictures). This switch can be used to specify the persistence of the credential. The options are:
-
Session
: The credential is stored for the duration of the current session. Logging out or rebooting will remove the credential. -
LocalMachine
: The credential is stored for the current user on the local machine. The credential will persist across sessions but will not be available to other users on the machine. -
Enterprise
: The credential available to all authenticated users on the domain.
If you don’t specify a persistence level the default is Session
.
Source: dev.to
Retrieving Credentials In PowerShell
To retrieve a credential in PowerShell you can use the Get-StoredCredential
cmdlet. Here’s an example:
Get-StoredCredential -Target 'MyCredential
However this does not show us much useful information. If you want to see details including the password we can add the -AsCredentialObject
switch:
Get-StoredCredential -Target 'MyCredential -AsCredentialObject
Also, note, that for credentials gathered using a method where the password has not been passed in plain text, such as the example above using Get-Credential
, the password can still be retrieved using this method.
So, if there’s a credential saved in Credential Manager that you need to find the password for, because you’ve forgotten or lost it, you can use this cmdlet to retrieve it.
In some instances you may wish to query the credentials to the console but not reveal the password. The TUN.CredentialManager
module has an additional switch, -ExcludeClearPassword
which will allow you to do this
Get-StoredCredential -Target 'MyCredential -ExcludeClearPassword -AsCredentialObject
More usefully though is going to be using the credential in a script. Here’s an example of how you can use the credential in a script:
$Credential = Get-StoredCredential -Target 'MyCredential -AsCredentialObject
$Username = $Credential.UserName
$Password = $Credential.Password
Write-Output "Username: $Username"
Write-Output "Password: $Password"
Where the password is stored securely you may need to convert it back from a secure string to a plain text string. Here’s an example of how you can do that:
$Credential = Get-StoredCredential -Target 'MyCredential
$Username = $Credential.UserName
$securePW = $Credential.Password
$pw = ConvertFrom-SecureString -SecureString $securePW -AsPlainText
Write-Output "Username: $Username"
Write-Output "Password: $pw"
Anyway, let’s look at a real use case for all of this. In the example below I have an API key for OpenWeatherMap stored in Credential Manager. I can retrieve this key and use it in a script to get the current weather for a location:
$owm = Get-StoredCredential -Target openweathermap-api -AsCredentialObject
Invoke-RestMethod -Uri "https://api.openweathermap.org/data/2.5/weather?q=London&appid=$($owm.Password)" -Method Get
So now we have a method for securely storing and using credentials in PowerShell scripts.
Removing Credentials In PowerShell
To remove a credential in PowerShell you can use the Remove-StoredCredential
cmdlet. Here’s an example:
Remove-StoredCredential -Target 'MyCredential
Command Prompt Credential Manager Tools
The Command Prompt (cmd
) doesn’t have the same level of capability as PowerShell but it does have a couple of commands that can be used to work with the Credential Manager. The cmdkey
command can be used to add, list, and remove credentials from the Credential Manager.
Note this time we have a list option which actually isn’t available in the PowerShell cmdlets. Your mileage may vary but this could still make cmdkey
a useful tool for you.
The major drawback to using cmdkey
is that it doesn’t have the ability to recover the password for a credential. This means that it is much more limited for scripting as we cannot lookup a password to use in a script.
Listing Credentials In Command Prompt
To list the credentials in the Credential Manager using the Command Prompt you can use the cmdkey
command with the /list
switch. Here’s an example:
cmdkey /list
Adding Credentials In Command Prompt
To add a credential in the Credential Manager using the Command Prompt you can use the cmdkey
command with the /add
or /generic
switch. As with the other examples we’ll be adding a generic credential in this example. Here’s an example:
cmdkey /add:MyCredential /user:MyUsername /pass:MyPassword
That’s about all there is to it. As I mentioned earlier, the major drawback to using cmdkey
is that it doesn’t have the ability to recover the password for a credential making it a much more limited tool.
Removing Credentials In Command Prompt
To remove a credential in the Credential Manager using the Command Prompt you can use the cmdkey
command with the /delete
switch. Here’s an example:
cmdkey /delete:MyCredential
Conclusion
In this article, we’ve looked at how to manage secrets in Windows using the Credential Manager. We’ve seen how to add, edit, and remove credentials in the GUI, and how to do the same in the command line using PowerShell and the Command Prompt. We’ve also seen how to retrieve credentials and use them in scripts. We’ve also seen how to use the cmdkey
command in the Command Prompt to manage credentials.
Most importantly, for me at least, I’ve covered the issue with the outdated CredentialManager
module for PowerShell and provided a way that we can continue to work with credentials using the newer TUN.CredentialManager
module.
Hopefully what you can take away from this article is that there are a number of ways to manage secrets in Windows and that if you are working with secrets in scripts on Windows you now have the tools to do so securely in a way that is integrated with the Windows operating system.
If this article helped inspire you please consider sharing this article with your friends and colleagues, or let me know via LinkedIn or X / Twitter. If you have any ideas for further content you might like to see please let me know too.