How do you manage/enforce licensing on a fully Sharepoint hosted app?
-
Sunday, November 18, 2012 4:58 PM
Hi,
I have currently building a Sharepoint hosted app (my first ever app!) for Sharepoint and have started investigating how I can licence it on the App store, but am getting highly confused!.
I'm struggling to work out how I can block functionality or people using the app without a licence on Sharepoint hosted apps, which are fully client side.
Ideally I need to be able to stop the site owner from adding new items to a list held on the app web (which powers a client app part) unless they have a valid licence. I do not want to put a check on the client web part itself, as this would mean the check is done by every user that visits the site, where as my plan is to have a one-time only cost that allows unlimited use by any number of users/sites on a tenant (Perpetual all user).
Any one any ideas, advice, good resources to learn more about this?
To summaries, I need advice on ways to licence / enforce licences by blocking use or functionality a fully Sharepoint hosted (client side) app.
Thanks!
Martin
All Replies
-
Monday, November 19, 2012 6:36 PMModerator
Hello Arktic,
The general process for licensing your apps is described in this post.
http://blogs.msdn.com/b/officeapps/archive/2012/11/09/licensing-your-apps-for-sharepoint.aspx
Specifically for SharePoint hosted apps we are working on a sample (should be ready in a day or 2) but the process is very similar, you retrieve*, verify and then use a license; I bet you can derive most of it from the sample in the post above.
Be aware though that for purely client side apps there are inherent limitations with the technology because all code is ultimately interpreted by the browser; obfuscating your code usually helps.
I'll keep this thread updated once we have the full sample.
*The retrieval portion can be done using our JS OM or REST. For the latter the syntax is similar to this:
http://<appweburl>/_api/SP.Utilities.Utility.GetAppLicenseInformation(guid'<productId>')
-
Monday, November 19, 2012 7:02 PM
Thanks Humberto! I'll have a play about and see if I can get it working, i was thinking about obfuscating the code to make it a bit more secure, but was worried that this might impact it getting accepted to the app store as that part of code would be hard to review?
Also looking forward to seeing the sample, so really appreciate your offer to post back in thread once its completed :)
-
Monday, November 19, 2012 7:55 PMModerator
Obfuscating your code shouldn't affect app validation for the store. There are multiple valid reasons (performance, security/etc.) that require minification and/or obfuscation of code.
I'll post the sample once we have it ready.
-
Wednesday, November 21, 2012 12:33 AMModerator
Ok so here is a rough draft of the sample code (put this in App.js to see how it works). It still needs polish but I wanted to post this right away just in case. Whenever I have a polished version I'll update the thread but this should get you going.
To test your code, you can use the tools included in this post to import a test license:
http://blogs.msdn.com/b/officeapps/archive/2012/11/09/licensing-your-apps-for-sharepoint.aspx
var context; var licenseCollection; var topLicense; var encodedTopLicense; var verifiedLicense; var response; // This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model $(document).ready(function () { context = SP.ClientContext.get_current(); //Retrieve license from SharePoint; change this productId with the one for your app; you can get it from AppManifest.xml licenseCollection = SP.Utilities.Utility.getAppLicenseInformation(context, '{b7224c84-b20c-45b0-88ab-a9f897f7aa4f}'); context.executeQueryAsync(onRetrieveLicenseFromSPSuccess, onRetrieveLicenseFromSPFailure); }); //Retrieval call succeded (doesn't mean there is a license, look at the contents to see if there is one) function onRetrieveLicenseFromSPSuccess() { if (licenseCollection.get_count() > 0) { topLicense = licenseCollection.get_item(0).get_rawXMLLicenseToken(); //debug alert("License retrieved from SharePoint: \n" + topLicense); //encode license; required to call the verification service since it will be sent on the URL encodedTopLicense = encodeURIComponent(topLicense); //debug, display the encoded license alert("License ready to be verified:\n" + encodedTopLicense); } else { alert("The user doesn't have a license"); } //Call verification service via the WebProxy; this ensures the validity of the license in case SharePoint was tampered with var request = new SP.WebRequestInfo(); //We use the REST flavor of the verification service request.set_url("https://verificationservice.officeapps.live.com/ova/verificationagent.svc/rest/verify?token=" + encodedTopLicense); request.set_method("GET"); response = SP.WebProxy.invoke(context, request); // Set the event handlers and invoke the request context.executeQueryAsync(onVerificationCallSuccess, onVerificationCallFailure); } // This function is executed if the above call fails function onRetrieveLicenseFromSPFailure(sender, args) { alert('Failed to retrieve license:' + args.get_message()); } function onVerificationCallSuccess() { var stories; var storiesHTML; var xmlDOM; //It is highly recommended to cache (e.g. cookies) the response //If you are concerned about tampering only re-retrieve and re-validate the license for sensitive operations in your App. var verificationResponse= response.get_body(); //Debug, display the raw response alert("Verification Service Response" + verificationResponse); xmlDoc = $.parseXML(verificationResponse); $xml = $(xmlDoc); licenseType = $xml.find("EntitlementType").text(); licenseIsValid = $xml.find("IsValid").text(); licenseIsTest = $xml.find("IsTest").text(); //DO SOMETHING NOW THAT YOU KNOW WHAT TYPE OF LICENSE THE USER HAS switch (licenseType) { case "Free": alert("Free app"); break; case "Paid": alert("Paid app"); break; case "Trial": alert("Trial app"); //You can then look at the expiration date on the response break; } } function onVerificationCallFailure() { alert('Failed to call verification service via WebProxy:' + args.get_message()); }
Program Manager, Office Developer Platform.
- Proposed As Answer by Humberto LezamaMicrosoft Employee, Moderator Wednesday, November 21, 2012 12:36 AM
- Edited by Humberto LezamaMicrosoft Employee, Moderator Wednesday, November 21, 2012 12:39 AM
- Marked As Answer by Humberto LezamaMicrosoft Employee, Moderator Wednesday, November 21, 2012 6:32 PM
-
Wednesday, November 21, 2012 12:30 PMYou sir, are a legend! thanks, this example is really helpful :)
-
Wednesday, November 28, 2012 9:27 PMI think it's a great concept to check licensing in client side javascript code - nobody will ever be able to steal your code and remove your license check in 60 seconds.
-
Friday, December 07, 2012 2:31 PMAnswererIt's a risk, but then again I think are people really going to go through the effort to remove my license check for an app that costs a few hundred dollars at most? Maybe, but we're also talking about business people using SharePoint and not kids trying to steal the latest game.
Corey Roth - SharePoint Server MVP blog: www.dotnetmafia.com twitter: @coreyroth

