How to protect files with Selective Wipe (XAML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

You can use selective wipe to identify protected files in your app that can be revoked when a user of your app is no longer authorized to your app data. This is a common scenario for businesses that allow employees to bring their own device to work. When the employee leaves the company, the company files on their personal device can be removed.

For example, an employee brings their personal tablet computer to the office and uses it for business e-mails. The e-mail app can protect all files that are used to store company e-mails locally on the computer using Selective Wipe. This associates those files with the company using an enterprise identifier, such as "sample.com". If the user is no longer an employee of the company, then the next time that they open the company e-mail app, the app can determine that the user is no longer an employee and tell Selective Wipe to revoke access to all files protected for their enterprise identifier. When the app attempts to access a file and determines that it is revoked, the app can then delete the file.

Prerequisites

  • The sample code in this topic assumes that the following global variables are set.

    ApplicationData appRootFolder = ApplicationData.Current;
    string enterpriseIdentity = "example.com";
    int AccessDeniedHResult = -2147024891;  // Access Denied (0x80070005)
    

Protect a file or folder using Selective Wipe

You can use the ProtectAsync method to protect a file or folder using Selective Wipe. This identifies the file as protected for your enterprise identifier, such as "example.com", as shown in the previous code example. If you protect a folder using the ProtectAsync method, then all files in that folder inherit the same protection.

// Add a folder and protect it using Selective Wipe.
private async Task<StorageFolder> AddFolder(string folderName)
{
    StorageFolder newFolder = await appRootFolder.LocalFolder.CreateFolderAsync(folderName);

    var status = await ProtectItem(newFolder, enterpriseIdentity);

    return newFolder;
}

// Add a file and protect it using Selective Wipe.
private async Task<StorageFile> AddFile(string fileName, StorageFolder folder)
{
    StorageFile newFile = await folder.CreateFileAsync(fileName);

    var status = 
        await Windows.Security.EnterpriseData.FileRevocationManager.
            GetStatusAsync(newFile);

    if (status != Windows.Security.EnterpriseData.FileProtectionStatus.Protected)
    {
        status = await ProtectItem(newFile, enterpriseIdentity);
    }

    return newFile;
}

private async Task<Windows.Security.EnterpriseData.FileProtectionStatus> 
    ProtectItem(IStorageItem item, string enterpriseIdentity)
{
    var status = 
        await Windows.Security.EnterpriseData.FileRevocationManager.
            ProtectAsync(item, enterpriseIdentity);

    return status;
}

Revoke access to protected files and folders

When your app determines that a user is no longer valid, you can quickly revoke access to all of the files and folders protected for an enterprise identity using the Revoke method, as shown in the following example. The file is not deleted by the Revoke method. The Revoke method puts the file into state where it cannot be accessed. You can add code to your app to delete a file that is inaccessible and has been revoked, which is shown in the next example.

private void InitializeApp(string userName)
{
    if (GetUserStatus(userName) == AppUserStatus.NotFound)
    {
        Windows.Security.EnterpriseData.FileRevocationManager.Revoke(enterpriseIdentity);
    }
}

Get the status of a file

You can use the GetStatusAsync method to determine the Selective Wipe protection status of a file or folder. This will tell you if a file is protected or not, if a file is protected by another user on the computer, and so on. A common use of the GetStatusAsync method is to determine when a protected file should be deleted. For example, when a protected file is revoked, an attempt to access the file contents will result in an "Access is denied" exception. When you encounter that exception, you can use the GetStatusAsync method to determine if the file has been revoked by Selective Wipe and then delete the file if it has, as shown in the following example.

private async Task<IRandomAccessStream> GetFileContents(string filePath)
{
    IRandomAccessStream stream = null;
    StorageFile file = null;

    try
    {
        file = await StorageFile.GetFileFromPathAsync(filePath);
        stream = await file.OpenReadAsync();
    }
    catch (UnauthorizedAccessException e)
    {
        if (e.HResult == AccessDeniedHResult)
        {
            // Delete file if it has been revoked.
            SelectiveWipeCleanup(file);
        }

        return null;
    }

    return stream;
}

// Delete items revoked by Selective Wipe.
private async void SelectiveWipeCleanup(StorageFile file)
{
    var status = await Windows.Security.EnterpriseData.FileRevocationManager.GetStatusAsync(file);
    if (status == Windows.Security.EnterpriseData.FileProtectionStatus.Revoked)
    {
        await file.DeleteAsync();
    }
}

Copy a protected file

When you copy a file using the CopyAsync or CopyAndReplaceAsync methods, the Selective Wipe protection from the copied file is not automatically applied to the new copy of the file. This applies to files where you "save as" a new file. In this case, you can copy the Selective Wipe protection from the original file using the CopyProtectionAsync method, as shown in the following example.

public async Task<bool> CopyFile(StorageFile file, StorageFolder newFolder) 
{
    bool result = false;

    try
    {
        var newFile = await file.CopyAsync(newFolder);
        result = await 
            Windows.Security.EnterpriseData.FileRevocationManager.
            CopyProtectionAsync(file, newFile);
        }
    catch (Exception e) 
    {
        // Handle exception. For example, copy already exists.
    }

    return result;
}

Complete example

FileRevocationManager sample

Windows.Security.EnterpriseData namespace

Securing apps