The other day I answered a question on stack overflow regarding the WinRT credential picker, and oddly enough, I got almost exactly the same question from another person.

Let me preface all this with the note that the CredentialPicker was designed for enterprise authentication scenarios, as it has a built-in capability to save credentials elsewhere if you instruct it to (see the chart on page 659 of my book PDF. For other scenarios, you can still use the picker if you want, or you might just implement your own controls. Alternately, if you’re authenticating with a service of your own, you can do this with the Web Authentication Broker and keep the credentials on the server. I have to admit that my impression of the Web Auth Broker has been that it’s for use with OAuth providers, but it’s not limited to that: it can be used with any site that has a page to authenticate and respond with an access token that the client can then store (in the credential locker).

Anyway, back to the credential picker. The question is one of saving credentials that a user enters in the Windows.Security.Credentials.UI.CredentialPicker, which comes back as a CredentialPickerResults object from the pickAsync method.

This results object has two properties, credentialUserName and credentialPassword, that are returned in plain text for certain input protocols (Basic and Digest). You can do with these whatever you want, but the important thing is that if you persist them to storage, be sure to use the Credential Locker–do not save them as plain text. A key benefit of the Credential Locker is that those credentials will roam to the user’s other devices, where your app can retrieve them even on first run and not have to bother the user again. (Refer to the Credential Locker sample for usage of the API.)

Note that if the input protocol for your device is something other than Basic or Digest, the credentialPassword comes back encrypted. The default protocol, Negotiate, could go either way (on my machine, which is domain-joined, the protocol is probably enforced through group policy so the password is encrypted). So if you need plain-text passwords back from the credential picker, use the variant of pickAsync that allows you to specify options, and set the the input protocol to Windows.Security.Credentials.UI.AuthenticationProtocol.basic. You can try this is scenario 3 of the Credential Picker sample.

Note also that if you’re transmitting such credentials over the Internet, always use https:// or be sure to encrypt that information on a unsecured URI. Never, ever transmit plain text credentials!

Anyway, the username and password fields from the CredentialPickerResults is enough to authenticate with whatever service you need, but the second question is how to get those credentials back into the credential picker at a later time? The picker’s options don’t support plain text username and password field as input. The picker does, however, accept a previousCredential object, which is basically a byte array (a buffer object) that contains a scramble of those credentials.

This buffer is what comes back from pickAsync in the CredentialPickerResults.credential property. During the same app session, you can simply store this value in memory and drop it into previousCredential for the next call to pickAsync.

More likely, though, you’ll want to save that buffer in appdata for use in later sessions. To do this you use the methods in Windows.Storage.FileIO, namely writeBufferAsync and readBufferAsync. Here’s some code I added to the completed handler for pickAsync in scenario 3 of the Credential Picker sample:

//results.credential will be null if the user cancels
if (results.credential != null) {
    //Having retrieved a credential, write the opaque buffer to a file
    var option = Windows.Storage.CreationCollisionOption.replaceExisting;
    Windows.Storage.ApplicationData.current.localFolder.createFileAsync(“credbuffer.dat”, option).then(function (file) {
        return Windows.Storage.FileIO.writeBufferAsync(file, results.credential);
    }).done(function () {
        //No results for this operation
        console.log(“credbuffer.dat written.”);
    }, function (e) {
console.log(“Could not create credbuffer.dat file.”);
    });
}

Then I created a new function to load that credential, if possible. This is called on the Launch button click instead of launchCredPicker in the sample:

//In the page ready method:
document.getElementById(“button1”).addEventListener(“click”, readPrevCredentialAndLaunch, false);

//Added
function readPrevCredentialAndLaunch() {
    Windows.Storage.ApplicationData.current.localFolder.getFileAsync(“credbuffer.dat”).then(function (file) {
        return Windows.Storage.FileIO.readBufferAsync(file);
    }).done(function (buffer) {
        console.log(“Read from credbuffer.dat”);
launchCredPicker(buffer);
}, function (e) {
console.log(“Could not reopen credbuffer.dat; launching default”);
        launchCredPicker(null);
    });
}

//Modified to take a buffer
function launchCredPicker(prevCredBuffer) {
    try {
       var options = new Windows.Security.Credentials.UI.CredentialPickerOptions();
       //Other options omitted

       if (prevCredBuffer != null) {
           options.previousCredential = prevCredBuffer;
       }

   //…

That’s it. I put the modified JS sample on http://www.kraigbrockschmidt.com/src/CredentialPickerJS_modified.zip.


Comments are closed