Licensing your apps for SharePoint

This blog post is brought to you by Humberto Lezama Guadarrama. Humberto is a Program Manager in the Office Developer Platform team. He is the PM of the apps licensing infrastructure for SharePoint 2013.

In a previous post, Creating and verifying licensing in a paid app for Office, Krishnan explained how to license apps for Office, and today I’ll drill down on how the process works for apps for SharePoint. While both types of apps share the same infrastructure, some important aspects of the SharePoint implementation are worth highlighting. I’ll start by explaining how licensing acquisition and assignment works and then talk about the steps that you as a developer need to take to properly license your apps.

License acquisition and assignment

When someone purchases an app for SharePoint from the store, a representation of the license is sent to SharePoint in the form of a license token. The token contains information about the purchase, such as how many seats were purchased, acquisition time, license expiration date, etc.; the information varies according to the license type (free, trial, and paid). Developers define which types they support when submitting an app to the store, as outlined in David’s post, which business model is right for your app?

SharePoint uses the information on the license token and provides a user interface to assign the people who will have a license—think ”named users.” Seat assignment is only required on per-user purchases. Unlimited license types, such as free apps and site licenses, don’t require assignment of users. SharePoint also allows you to designate license managers, who are the folks allowed to add/remove users to the license. The following image shows the License Management UI.

image
Figure 1. License Management UI

The license token also contains information to periodically renew it or revoke it if the need arises (e.g. fraud); SharePoint takes care of those tasks automatically. Full details on how licensing works, as well as the license token schema, is published in Licensing apps for Office and SharePoint, which is also available on https://dev.office.com.

License enforcement

The role of SharePoint in licensing is that of a broker: once it retrieves a license token from the Office Store, it allows license managers to add or remove users to a given license (up to the number purchased). But it does NOT enforce the license. Your app MUST add code to enforce licensing. Why? Because we believe that a one-size-fits-all enforcement mechanism would not produce a good experience for users or developers. Each app provides a different set of functionality, so having us arbitrarily enforce licensing for all apps would produce suboptimal results.

As a result, we opted to give developers flexibility while still providing guidance to properly enforce and surface licensing information. The process is pretty straightforward: developers use SharePoint APIs to retrieve a license token and then call the store verification service to validate it. We strongly recommend the validation step because the token could potentially be tampered with while in transit. Once the token is validated, the app can make decisions based on the license, such as providing informative messages, as outlined in our UI guidelines. The following diagram summarizes the process.

image
Figure 2. Licensing process

Adding code to license your apps

OK, but how do you add code in your apps to enforce licensing? Even more important, how do you simulate licensing BEFORE submitting your app to the store to ensure you code is behaving as it should? The detailed process is described in How to: Add license checks to your app for SharePoint. It consists of three main steps: import a test license, add code to your app that retrieves and validates the license, and then make decisions based on the outcome. Easy, right? No? Not easy enough? OK, OK, I’ll do one better. What about an actual app sample that does all of the above and contains helper classes? Much better, right? The full code sample is available on Code Gallery.

Step 1: Import a test license

The sample mentioned above is an autohosted app that you can deploy on your Office 365 Developer Site. Simply deploy the .app package (using the app catalog, or directly on your dev site by adding it to your Apps in testing section). The sample allows you to import and manage licenses, and it also has code that shows how to retrieve, validate, and signal licensing states. You can also peruse the code and use the helper classes in your own project if you want.

To import a test license, all you have to do is run the app and select the type of license you want to import. Or, you can also import licenses using our APIs, as described in How to: Add license checks to your app for SharePoint. But I highly recommend using the app instead; it will save you munching XML. The sample app and tools are shown here.

image
Figure 3. Sample app and tools

Step 2: Add code to retrieve and validate a license

Using the helper classes on the sample, you can easily retrieve a license and then make decisions about it. The helper code takes care of most of the heavy lifting, including calling the verification service. Below is a simple code snippet of an ASP.NET page that uses the helper classes.

 using Microsoft.SharePoint.Client;
using System;
using LicenseSPAppSampleWeb.LicenseVerificationService;

namespace LicenseSPAppSampleWeb.Pages
{
  public partial class ValidateLicense : System.Web.UI.Page
  {
    bool _testMode = true;

    protected void Page_Load(object sender, EventArgs e)
    {
      //ProductId must match the one on the AppManifest.xml of the 
      //SharePoint App that is retrieving its license.
      //An app can only retrieve its own licenses for security reasons
      //(e.g. you cannot retrieve other Apps licenses)
      //The one hardcoded here matches this test app

      Guid ProductId = new Guid("7c617a53-6f45-4d23-ada0-28eabb744acb");
      string uiWarningMessage = null;

      //Get Context token to call SP; standard oAuth
      string contextToken = Session["contexToken"].ToString();

      TokenHelper.TrustAllCertificates();
      ClientContext ctx = 
        TokenHelper.GetClientContextWithContextToken(
          Session["SPHostUrl"].ToString(), 
          Session["contexToken"].ToString(), 
          Request.Url.Authority);

      //Use helper method to retrieve a processed license object
      //It is recommended to CACHE the VerifyEntitlementTokenResponse 
      //result until the storeLicense.tokenExpirationDate
      VerifyEntitlementTokenResponse verifiedLicense = 
        SPAppLicenseHelper.GetAndVerifyLicense(ProductId, ctx);

      //Get UI warning. 
      //Note that the name of the app is being hardcoded to Cheezburgers 
      //because is an app that already exists on the marketplace
      //You should use your exact app display name instead 
      //(make sure name matches with metadata you submit to seller dashboard)
      uiWarningMessage = 
        SPAppLicenseHelper.GetUIStringText(
          verifiedLicense, 
          Session["SPHostUrl"].ToString(), 
          Request.Url.ToString(), 
          "Cheezburgers", 
          "Features X, Y, Z");

      if (verifiedLicense == null)
      {
        //No license found or the license was malformed
        //The UI string retrieved above will 
        //already contain the appropiate info
        //In real app code you could take additional steps 
        //(e.g. provide reduced functionality)
      }
      else
      {
        //There is a well-formed license; 
        //must look at properties to determine validity
        if (verifiedLicense.IsValid)
        {
          //Valid production license
          //For app sample purposes display 
          //'Production License' + the corresponding warning text; 
          //replace this with your own logic. 
          uiWarningMessage = "Production License: " + uiWarningMessage;
          processLicense(verifiedLicense);
        }
        else if (verifiedLicense.IsTest && _testMode == true)
        {
          //Test mode with valid test token
          //For debug we just display 
          //'Test License' plus the corresponding UI warning text; 
          //in a real world production scenario
          //_testMode should be set to false
          //and the test license should be rejected. 
          uiWarningMessage = "Test License: " + uiWarningMessage;
          processLicense(verifiedLicense);
        }
        else
        {
          //Beep, production mode with invalid license
          //Warn the user about missing/invalid license
          uiWarningMessage = "Invalid License!!! " + uiWarningMessage;
        }
      }

      //Sets the text of the alert
      lblWarning.Text = uiWarningMessage;
    }

    protected void processLicense(
      VerifyEntitlementTokenResponse verifiedLicense)
    {
      SPAppLicenseType licenseType = 
        SPAppLicenseHelper.GetLicenseTypeFromLicense(verifiedLicense);
      switch (licenseType)
      {
        case SPAppLicenseType.Trial:
          //Do something for a valid trial
          //besides presenting a message on the UI
          if (SPAppLicenseHelper.GetRemainingDays(verifiedLicense) > 0)
          {
            //Valid trial
            //The UI string retrieved above will already 
            //contain the appropiate info
            //In real app code you could take additional steps 
            //(we encourage trials to be fully featured) 
            //Helper code will return int.MaxValue for an unlimited trial
          }
          else
          {
            //Expired trial
            //The UI string retrieved above will already 
            //contain the appropiate info
            //In real app code you could take additional steps
            //(e.g. provide reduced functionality) 
          }
          break;
        case SPAppLicenseType.Paid:
          //Do something for a paid app
          break;
        case SPAppLicenseType.Free:
          //Do something for a free app
          break;
        default:
          throw new Exception("Unknown License Type");
      }
    }
  }
}

If you want to make all the calls on your own without the helper code, you can also do that; you will have to add a reference to the verification service, as described in Krishnan’s post, and use it in conjunction with SharePoint APIs to first retrieve and then verify the license.

Update: You can download the VS solution here.

Step 3: Make decisions based on the app license

This is really up to you to decide, but we always encourage you to provide as much functionality in your app as possible. Weakening an unlicensed app to the point of making it unusable is probably not in your best interest. You want to entice customers into buying a license for your app while still safeguarding valuable functionality. If you need to inform users about their licensing state, the sample code provided contains helper methods to display UI warnings in case you need to show one (e.g for an expired trial); the messages follow our UX guidelines.

OK, so that is pretty much the core of what you need to know about licensing. If you have questions or comments, by all means please post them here or hit our Apps for SharePoint 2013 forum; our team is constantly monitoring it and would be happy to help out if you encounter any problems.

Happy coding!