Skip to content

Commit 691d5d4

Browse files
Merge pull request #5599 from MicrosoftDocs/copilot/fix-2253
Fix smart cards authentication example - show how to obtain adminKey
2 parents 9044989 + f1dc3f6 commit 691d5d4

File tree

1 file changed

+68
-2
lines changed

1 file changed

+68
-2
lines changed

hub/apps/develop/security/smart-cards.md

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,64 @@ Once [RequestVirtualSmartCardCreationAsync](/uwp/api/windows.devices.smartcards.
8484

8585
To authenticate with smart cards or virtual smart cards, your app must provide the behavior to complete challenges between the admin key data stored on the card, and the admin key data maintained by the authentication server or management tool.
8686

87+
### Obtaining the admin key
88+
89+
Before you can perform authentication, you need to obtain the admin key. The source of the admin key depends on your scenario:
90+
91+
- **For virtual smart cards you created**: Use the same admin key that was generated during card creation (as shown in the "Create a virtual smart card" section above). You should store this key securely for later authentication use.
92+
- **For existing physical or virtual smart cards**: The admin key is typically provided by your organization's IT department, card management system, or the service that issued the card.
93+
- **For development/testing**: You can generate a test admin key using [CryptographicBuffer.GenerateRandom](/uwp/api/windows.security.cryptography.cryptographicbuffer.generaterandom) as shown in the virtual card creation example below.
94+
95+
```cs
96+
// Example: Store the admin key from virtual card creation for later use
97+
IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);
98+
99+
// Store this key securely in your app (e.g., in app settings, secure storage, etc.)
100+
// You'll need this same key for authentication operations
101+
102+
SmartCardProvisioning provisioning = await
103+
SmartCardProvisioning.RequestVirtualSmartCardCreationAsync(
104+
"Card friendly name",
105+
adminkey,
106+
pinPolicy);
107+
108+
// Save the adminkey for future authentication
109+
SaveAdminKeySecurely(adminkey);
110+
```
111+
112+
### Example admin key management methods
113+
114+
Here are example methods you might implement to securely store and retrieve admin keys:
115+
116+
```cs
117+
// Example implementation for storing admin key securely
118+
private void SaveAdminKeySecurely(IBuffer adminKey)
119+
{
120+
// Convert to string for storage (consider encryption for production)
121+
string adminKeyString = CryptographicBuffer.EncodeToBase64String(adminKey);
122+
123+
// Store in app settings (consider using Windows Credential Manager for production)
124+
ApplicationData.Current.LocalSettings.Values["SmartCardAdminKey"] = adminKeyString;
125+
}
126+
127+
// Example implementation for retrieving stored admin key
128+
private IBuffer GetStoredAdminKey()
129+
{
130+
// Retrieve from app settings
131+
string adminKeyString = ApplicationData.Current.LocalSettings.Values["SmartCardAdminKey"] as string;
132+
133+
if (string.IsNullOrEmpty(adminKeyString))
134+
{
135+
throw new InvalidOperationException("Admin key not found. Ensure the smart card was created by this app or the admin key was provided by your IT department.");
136+
}
137+
138+
// Convert back to IBuffer
139+
return CryptographicBuffer.DecodeFromBase64String(adminKeyString);
140+
}
141+
```
142+
143+
### Authentication algorithm
144+
87145
The following code shows how to support smart card authentication for services or modification of physical or virtual card details. If the data generated using the admin key on the card ("challenge") is the same as the admin key data provided by the server or management tool ("adminkey"), authentication is successful.
88146

89147
```cs
@@ -123,9 +181,14 @@ SmartCardProvisioning provisioning =
123181
SmartCardChallengeContext context =
124182
await provisioning.GetChallengeContextAsync();
125183

184+
// Use the admin key that was either:
185+
// 1. Generated during virtual card creation, or
186+
// 2. Provided by your IT department/card management system
187+
IBuffer adminKey = GetStoredAdminKey(); // Your method to retrieve the stored admin key
188+
126189
IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(
127190
context.Challenge,
128-
rootPage.AdminKey);
191+
adminKey);
129192

130193
verifyResult = await context.VerifyResponseAsync(response);
131194
```
@@ -163,10 +226,13 @@ bool result = await provisioning.RequestPinResetAsync(
163226

164227
try
165228
{
229+
// Use the same admin key from card creation or your secure storage
230+
IBuffer adminKey = GetStoredAdminKey(); // Your method to retrieve the stored admin key
231+
166232
IBuffer response =
167233
ChallengeResponseAlgorithm.CalculateResponse(
168234
request.Challenge,
169-
rootPage.AdminKey);
235+
adminKey);
170236
request.SetResponse(response);
171237
}
172238
finally

0 commit comments

Comments
 (0)