|
| 1 | +--- |
| 2 | +title: Credential locker for Windows apps |
| 3 | +description: This article describes how Windows apps can use the Credential Locker to securely store and retrieve user credentials. |
| 4 | +ms.date: 08/05/2024 |
| 5 | +ms.topic: how-to |
| 6 | +#customer intent: As a Windows developer, I want to learn how I can integrate the Credential Locker APIs into my native apps to store and retrieve user credentials. |
| 7 | +--- |
| 8 | + |
| 9 | +# Credential locker for Windows apps |
| 10 | + |
| 11 | +This article describes how Windows apps can use the Credential Locker to securely store and retrieve user credentials, and roam them between devices with the user's Microsoft account. |
| 12 | + |
| 13 | +The Windows Runtime (WinRT) APIs for Credential Locker access are part of the [Windows Software Development Kit (SDK)](https://developer.microsoft.com/windows/downloads/windows-sdk/). These APIs were created for use in Universal Windows Platform (UWP) apps, but they can also be used in WinUI apps or in packaged desktop apps, including WPF and Windows Forms. For more information about using WinRT APIs in your Windows desktop app, see [Call Windows Runtime APIs in desktop apps](/windows/apps/desktop/modernize/desktop-to-uwp-enhance). |
| 14 | + |
| 15 | +## Overview of the sample scenario |
| 16 | + |
| 17 | +For example, you have an app that connects to a service to access protected resources such as media files, or social networking. Your service requires login information for each user. You've built UI into your app that gets the username and password for the user, which is then used to log the user into the service. Using the Credential Locker API, you can store the username and password for your user and easily retrieve them and log the user in automatically the next time they open your app, regardless of what device they're on. |
| 18 | + |
| 19 | +User credentials stored in the Credential Locker do *not* expire, are *not* affected by the [ApplicationData.RoamingStorageQuota](/uwp/api/windows.storage.applicationdata.roamingstoragequota), and will *not* be cleared out due to inactivity like traditional roaming data. However, you can only store up to 20 credentials per app in the Credential Locker. |
| 20 | + |
| 21 | +Credential Locker works a little differently for domain accounts. If there are credentials stored with your Microsoft account, and you associate that account with a domain account (such as the account that you use at work), your credentials will roam to that domain account. However, any new credentials added when signed on with the domain account won’t roam. This ensures that private credentials for the domain aren't exposed outside of the domain. |
| 22 | + |
| 23 | +## Storing user credentials |
| 24 | + |
| 25 | +1. Obtain a reference to the Credential Locker using the [PasswordVault](/uwp/api/Windows.Security.Credentials.PasswordVault) object from the [Windows.Security.Credentials](/uwp/api/Windows.Security.Credentials) namespace. |
| 26 | +1. Create a [PasswordCredential](/uwp/api/Windows.Security.Credentials.PasswordCredential) object that contains an identifier for your app, the username and the password, and pass that to the [PasswordVault.Add](/uwp/api/windows.security.credentials.passwordvault.add) method to add the credential to the locker. |
| 27 | + |
| 28 | +```cs |
| 29 | +var vault = new Windows.Security.Credentials.PasswordVault(); |
| 30 | +vault.Add(new Windows.Security.Credentials.PasswordCredential( |
| 31 | + "My App", username, password)); |
| 32 | +``` |
| 33 | + |
| 34 | +## Retrieving user credentials |
| 35 | + |
| 36 | +You have several options for retrieving user credentials from the Credential Locker after you have a reference to the [PasswordVault](/uwp/api/Windows.Security.Credentials.PasswordVault) object. |
| 37 | + |
| 38 | +- You can retrieve all the credentials the user has supplied for your app in the locker with the [PasswordVault.RetrieveAll](/uwp/api/windows.security.credentials.passwordvault.retrieveall) method. |
| 39 | +- If you know the username for the stored credentials, you can retrieve all the credentials for that username with the [PasswordVault.FindAllByUserName](/uwp/api/windows.security.credentials.passwordvault.findallbyusername) method. |
| 40 | +- If you know the resource name for the stored credentials, you can retrieve all the credentials for that resource name with the [PasswordVault.FindAllByResource](/uwp/api/windows.security.credentials.passwordvault.findallbyresource) method. |
| 41 | +- Finally, if you know both the username and the resource name for a credential, you can retrieve just that credential with the [PasswordVault.Retrieve](/uwp/api/windows.security.credentials.passwordvault.retrieve) method. |
| 42 | + |
| 43 | +Let’s look at an example where we have stored the resource name globally in an app and we log the user on automatically if we find a credential for them. If we find multiple credentials for the same user, we ask the user to select a default credential to use when logging on. |
| 44 | + |
| 45 | +```cs |
| 46 | +private string resourceName = "My App"; |
| 47 | +private string defaultUserName; |
| 48 | + |
| 49 | +private void Login() |
| 50 | +{ |
| 51 | + var loginCredential = GetCredentialFromLocker(); |
| 52 | + |
| 53 | + if (loginCredential != null) |
| 54 | + { |
| 55 | + // There is a credential stored in the locker. |
| 56 | + // Populate the Password property of the credential |
| 57 | + // for automatic login. |
| 58 | + loginCredential.RetrievePassword(); |
| 59 | + } |
| 60 | + else |
| 61 | + { |
| 62 | + // There is no credential stored in the locker. |
| 63 | + // Display UI to get user credentials. |
| 64 | + loginCredential = GetLoginCredentialUI(); |
| 65 | + } |
| 66 | + |
| 67 | + // Log the user in. |
| 68 | + ServerLogin(loginCredential.UserName, loginCredential.Password); |
| 69 | +} |
| 70 | + |
| 71 | +private Windows.Security.Credentials.PasswordCredential GetCredentialFromLocker() |
| 72 | +{ |
| 73 | + Windows.Security.Credentials.PasswordCredential credential = null; |
| 74 | + |
| 75 | + var vault = new Windows.Security.Credentials.PasswordVault(); |
| 76 | + |
| 77 | + IReadOnlyList<PasswordCredential> credentialList = null; |
| 78 | + |
| 79 | + try |
| 80 | + { |
| 81 | + credentialList = vault.FindAllByResource(resourceName); |
| 82 | + } |
| 83 | + catch(Exception) |
| 84 | + { |
| 85 | + return null; |
| 86 | + } |
| 87 | + |
| 88 | + if (credentialList.Count > 0) |
| 89 | + { |
| 90 | + if (credentialList.Count == 1) |
| 91 | + { |
| 92 | + credential = credentialList[0]; |
| 93 | + } |
| 94 | + else |
| 95 | + { |
| 96 | + // When there are multiple usernames, |
| 97 | + // retrieve the default username. If one doesn't |
| 98 | + // exist, then display UI to have the user select |
| 99 | + // a default username. |
| 100 | + defaultUserName = GetDefaultUserNameUI(); |
| 101 | + |
| 102 | + credential = vault.Retrieve(resourceName, defaultUserName); |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + return credential; |
| 107 | +} |
| 108 | +``` |
| 109 | + |
| 110 | +## Deleting user credentials |
| 111 | + |
| 112 | +Deleting user credentials in the Credential Locker is also a quick, two-step process. |
| 113 | + |
| 114 | +1. Obtain a reference to the Credential Locker using the [PasswordVault](/uwp/api/Windows.Security.Credentials.PasswordVault) object from the [Windows.Security.Credentials](/uwp/api/Windows.Security.Credentials) namespace. |
| 115 | +1. Pass the credential you want to delete to the [PasswordVault.Remove](/uwp/api/windows.security.credentials.passwordvault.remove) method. |
| 116 | + |
| 117 | +```cs |
| 118 | +var vault = new Windows.Security.Credentials.PasswordVault(); |
| 119 | +vault.Remove(new Windows.Security.Credentials.PasswordCredential( |
| 120 | + "My App", username, password)); |
| 121 | +``` |
| 122 | + |
| 123 | +## Best practices |
| 124 | + |
| 125 | +Only use the credential locker for passwords and not for larger data blobs. |
| 126 | + |
| 127 | +Save passwords in the credential locker only if the following criteria are met: |
| 128 | + |
| 129 | +- The user has successfully signed in. |
| 130 | +- The user has opted to save passwords. |
| 131 | + |
| 132 | +Never store credentials in plain-text using app data or roaming settings. |
| 133 | + |
| 134 | +## Related content |
| 135 | + |
| 136 | +- [PasswordVault](/uwp/api/Windows.Security.Credentials.PasswordVault) |
| 137 | +- [Call Windows Runtime APIs in desktop apps](/windows/apps/desktop/modernize/desktop-to-uwp-enhance) |
0 commit comments