Securing your AutoCAD app using .NET

Many, many thanks for the congratulatory messages I received after my last post, whether via this blog, Twitter, LinkedIn or email. I was genuinely overwhelmed by the response! 🙂

Here's a post I've been meaning to write for some time: a common question I've seen, over the years, is about how best to implement copy protection or licensing in your application. While this post doesn't fully address that requirement, it does show you how to use a REST API to check the user entitlement for your application via the Autodesk App Store (formerly known as Autodesk Exchange Apps). This post is therefore really only relevant if you've posted your app there (or are considering it… just this mechanism could be enough of a reason for some to adopt this infrastructure).

The Entitlement API needs a couple of parameters to work: the "user ID" and the "app ID".

The user ID can be accessed in AutoCAD via the ONLINEUSERID sysvar which was introduced in AutoCAD 2014. It provides a unique ID that identifies the current user in the A360 back-end. If it's an empty string then the current user isn't logged in to A360.

The app ID can be determined using the URL for the app's entry in the Autodesk App Store. For instance, here's the link to the Screenshot app:

https://apps.autodesk.com/ACD/en/Detail/Index?id=appstore.exchange.autodesk.com%3ascreenshot%3aen

You can see the ID at the end, in this case it's appstore.exchange.autodesk.com:screenshot:en (%3a is the URI encoding for ":"). You can also find this ID for your own apps via the publishing mechanism.

The Entitlement API is really easy to use. For instance, here's a check to see whether the user with the made-up ID "1234567890" is entitled to use the Screenshot app:

https://apps.autodesk.com/webservices/checkentitlement?userid=1234567890&appid=appstore.exchange.autodesk.com%3ascreenshot%3aen

You should see this JSON string returned when you click on it:

{"UserId":"1234567890","AppId":"appstore.exchange.autodesk.com:screenshot:en","IsValid":false,"Message":"Ok"}

 

It's clearly a simple matter to check this API in your code. Here's some C# code that defines a CE command that checks the currently logged in user's entitlement for the Screenshot app. (You would want to change the ID for your own app's of course.)

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Newtonsoft.Json;

using System.Net;

using System.Threading.Tasks;

 

namespace EntitlementChecker

{

  public static class Extensions

  {

    public static async Task<bool> IsEntitled(

      this Editor ed, string userId, string appId

    )

    {

      using (var wc = new WebClient())

      {

        // Use the REST API to check entitlement

 

        try

        {

          var url =

            string.Format(

              "https://apps.autodesk.com/webservices/checkentitlement?userid={0}&appid={1}",

              System.Uri.EscapeUriString(userId), System.Uri.EscapeUriString(appId)

            );

          var res = await wc.DownloadStringTaskAsync(url);

 

          // Deserialize the response and return the entitlement value

 

          var json = JsonConvert.DeserializeObject<dynamic>(res);

          return (bool)json.IsValid;

        }

        catch (System.Net.WebException)

        {

          ed.WriteMessage("\nCould not access the online entitlement API.\n");

          return false;

        }

      }

    }

  }

 

  public class Commands

  {

    [CommandMethod("CE")]

    public static async void CheckEntitlement()

    {

      var doc = Application.DocumentManager.MdiActiveDocument;

      if (doc == null) return;

 

      var ed = doc.Editor;

 

      var appId = "appstore.exchange.autodesk.com:screenshot:en";

      var userId = (string)Application.GetSystemVariable("ONLINEUSERID");

 

      if (string.IsNullOrEmpty(userId))

      {

        ed.WriteMessage("\nYou are not logged in to the AutoCAD App Store.");

        return;

      }

 

      // Check entitlement

 

      var entitled = await ed.IsEntitled(userId, appId);

 

      ed.WriteMessage(

        "\nYou are {0}entitled to use app \"{1}\".\n",

        entitled ? "" : "not ", appId

      );

    }

  }

}

 

Right now I've implemented an extension method off the Editor class, mainly as I wanted to print a message to the command-line using WriteMessage(). In reality you'd probably want to throw an exception from within the check function and catch it in an our exception handler. At least that's what I'd look at doing for a real-world application.

Here's the CE command in action:

Checking for entitlement

I've deliberately kept things simple for this blog post. If you want to find out more about this topic – including best practices for dealing with offline use, etc. – then I recommend reading this ADN DevBlog post and this DevCenter article.

10 responses to “Securing your AutoCAD app using .NET”

  1. H Kean. I have some questions, to clarify the information.
    Question1. What for ":en" is added? If we have an app with name, for example, "abcdef" we MUST (usa.autodesk.com/ads... use:
    a) appstore.exchange.autodesk.com:abcdef

    Any other variants depend on localization, windows/mac version, etc:
    1) appstore.exchange.autodesk.com:abcdef:ru
    2) appstore.exchange.autodesk.com:abcdef_windows32and64:en
    3) appstore.exchange.autodesk.com:abcdef_windows32and64
    4) appstore.exchange.autodesk.com:abcdef_windows32
    5) appstore.exchange.autodesk.com:abcdef_windows64:fr

    So, variant "a" will work ALWAYS, variants "1-5" can return "false" in some cases. so, what for you teach us how to do it in wrong way? )))

    Question2. Yesterday i found out, that your free plugin "screenshot" returns "true" for valid users. But none of other FREE or DEMO plugins (cant guarantee 100%, cause i have checked it just for 20-30 free plugins))) ) is able to return "true", because TRUE - is just for paied plugins (as i know). So, what is your secret? )))

    1. Hi Nick,

      I posted a subset of the information published by the ADN team on this topic. For more specific information, feel free to post your questions via the DevBlog post or the email address listed in the DevCenter article.

      Best,

      Kean

  2. This is great. And very handy.

    I'd be interested to hear about solutions/ideas if one doesn't want to post on the exchange app store?

    1. Good question. There are a number of technologies out there for standalone licensing/copy protection (I don't have useful experience to share in this area myself).

      You might want to post to the discussion group, unless someone happens to see this question and post their suggestions here.

      Kean

  3. perfect thanks mate!

  4. Hi Kean! It seems like the Entitlement API is geared towards single users. However if multiple people log into 360 with the same ID and PW on multiple machines at the same time (ie different mac address) then the API wouldn't catch this. Is this true? Many large engineering firms have hundreds of computers running AutoCAD - I could see them using the same 360 ID and PW on each machine. If this is true said company could download a App once and use it on all of their machines at the same time. Is there anything to check the Mac Address with the entitlement to ensure a large company has paid for each computer using an App?

    1. Hi Billy,

      Good question. I doubt the API is geared towards picking up on usage of shared credentials. I suggest contacting the ADN team (or posting to the discussion groups) to get a definitive response.

      I'd be surprised if sharing credentials was allowed (legally) by the license agreement - and by our licensing systems - but I'm not a specialist in this area by any means.

      You could certainly check MAC addresses yourself for an extra level of security, but I don't believe this is built into this particular API (again - you should ask elsewhere to be sure).

      Cheers,

      Kean

  5. very helpful tutorial. BUT how to know appId before publish it in store?!
    It seems we need that in the code (before publishing!) for checking Entitlement...

    thanks

    1. Kean Walmsley Avatar

      Please post your question to one of the AutoCAD developer forums - someone involved in the publishing process will be able to help you.

      Kean

Leave a Reply

Your email address will not be published. Required fields are marked *