Skip to content

A desktop app gatekeeping and licensing solution using Azure Functions and Blob Storage

License

Notifications You must be signed in to change notification settings

adamfoneil/AOLicensing

Repository files navigation

This is an overhaul of a previous desktop app licensing solution I did about a year ago using Azure Functions, Azure Table Storage, and PayPal integration. This is really for my internal use, not a general-purpose reusable solution. But you should still get plenty of ideas on how to approach this looking my solution.

In this iteration, I've dropped the PayPal integration, and switched to blob storage via this KeyStore class. IMO blob storage is easier to work with than table storage, and will be good enough for this application. I'm expecting such low (if any) sales volume that I'm going to manually create license keys from a console app. The desktop gatekeeping is still in place. PayPal's developer story has gotten complicated, and it seems they no longer support the old-school IPN (instant payment notification) based on simple form posts and callbacks. I have a PayPal handler that I like. But like I say their story has become a forest of endless JavaScript, and I'm not having it.

  • The Function project has these functions:

    • CreateKey creates keys and saves them in blob storage with a customer's email address. I will trigger this manually from a console app when I get a payment notification. I will still use PayPal, but without IPN integration. This requires Function level permission because not just anyone can create keys.
    • ValidateKey is called from the Gatekeeper class. This allows anonymous access because anyone can validate a key.
    • QueryKey is used to help a customer find a lost key. Requires admin access.
  • The Desktop project is delivered as a NuGet package used in desktop apps. This is what I use to see if a product is activated. Apps would implement the Gatekeeper abstract class, and call StartLicensing to see if they are licensed. Example: ModelSync.

  • The Shared project has Models used both in the Deskop and Function projects. Note that the Desktop project uses linked members from the Shared project. Due to limitations of NuGet packaging, you can't include referenced projects. The next best thing is to link source files from the originating project, so that's what I do.

  • The KeyManager project is the console app I'll use to interact with my key storage. I would use this if someone buys a license and need a key generated. I used to automate this with PayPal IPN, but my sales volume is so low, and PayPal has so gotten complicated that I would rather generate keys manually. (My workload is still very low as the backend function generates and sends the key.)

Highlights and subtle points of interest

  • Azure Functions don't have MVC-style model binding, so I added this simple helper that matches query string fields with properties of an object. This uses LINQ Join method which I've been terrified of in the past.
  • This has been great practice for me with Refit. Aspects of this are hard to debug. I use a mix of Ngrok, Fiddler, and integration tests, but I'm getting better at this all the time. Refit is my favorite way to make API clients in C#.
  • I'm using Source Link in the Desktop (NuGet package) project. I've had good results with this recently elsewhere, but I'm unclear if this alone makes the debug experience better or if I also need to publish a separate symbols package.

About

A desktop app gatekeeping and licensing solution using Azure Functions and Blob Storage

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages