CodeGarden 10: The sixth annual Umbraco Developer Conference
June 23-25th 2010 - free ASP.NET MVC pre-conference. Register today!

Creating a license provider that interfaces with the Umbraco store

If anything is unclear in this article please contact me.

This document details how to create a license key generator for commercial Umbraco products that can be called by the Umbraco store post product purchase.

This article assumes that the Umbraco store license provider project will be used as a starting point though developers can simply implement the store specification for providing licenses.

Disclaimer

This is a simple licensing demonstration that any determined hacker could break.

Getting started

Download the Umbraco store license provider source code

The distribution is a standard asp.net web application based on spring.net and you may build and deploy as per your usual procedures.

The umbraco store will need a URL to access your license provider application so it will need to be hosted on a public facing webserver.

Configuration

Basic configuration of the license provider application is done by editing the applications web.config file

Logging

By default the application will log to a file named c:\temp\asplog.txt

You can modify the appender node of the log4net configuration section in your web.config file in order to change this location.

<log4net debug="true">
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="c:\temp\asplog.txt" />

Allowed hosts

As a security measure you can restrict access to your application by IP or hostname. A list of allowed hosts is configure in the following section of web.config

<object id="allowedHosts" type="System.Collections.Generic.List&lt;String>" >
    <constructor-arg name="collection">
        <list element-type="string">
            <value>localhost</value>
            <value>127.0.0.1</value>
            <value>store.umbraco.org</value>
            <value>www.darren-ferguson.com</value>
        </list>
        </constructor-arg>
</object>

Note: The IP of the live Umbraco store is 208.67.193.32

Configuring your store vendor name and ID

Your umbraco store vendor name and ID should be configured in the following section of web.config:

<object id="requestValidator" type="FergusonMoriyama.UmbracoStore.LicenseGen.Request.RemoteHostRequestValidator, FergusonMoriyama.UmbracoStore">
    <constructor-arg name="hosts" ref="allowedHosts"/>
    <constructor-arg name="vendorName" value="fergusonmoriyama"/>
    <constructor-arg name="vendorId" value="1"/>
</object>

Note: vendor name should be in lower case.

Add one or more encryption providers

The encryption provider is used to encrypt a license key string using a product specific key. The decrypt method will be used in your commercial umbraco package.

You'll need to implement one or more classes that implement the Encryption provider

public interface EncryptionProvider
    {
        String Encrypt(String textToEncrypt, String key);
        String Decrypt(String textToDecrypt, String key);
    }

The sample provided is as follows.

<object id="encryptionProvider" type="FergusonMoriyama.UmbracoStore.LicenseGen.Crypt.RijndaelSimpleEncryptionProvider, FergusonMoriyama.UmbracoStore">
        <constructor-arg name="saltValue" value="asljdasidua"/>
        <constructor-arg name="hashAlgorithm" value="SHA1"/>
        <constructor-arg name="passwordIterations" value="2"/>
        <constructor-arg name="initVector" value="@1B2c3D4e5F6g7H8"/>
        <constructor-arg name="keySize" value="256"/>
      </object>

Your commercial product will also need a reference to this encryption provider in order to decrypt the license key that they are provided with so it may be prudent to implement these in a separate assembly that can be referenced by other projects.

Add one or more license generators

License generators create a license key for your products based on information provided about the customer purchase.

License generators implement the LicenseGenerator interface:

public interface LicenseGenerator
    {
        bool providesLicenseType(string type);
        License generateLicense(
               string encryptionKey, string customerName, string email, string domain, string ip, int term);
       
    }

A product will have one or more license generators and a license will be generated using the first found license genator that provides a license of the appropriate type (using the providesLicenseType method).

Possible values of type are

1. Domain
2. Single-domain
3. IP
4. Open
5. Custom

A simplistic example is provided and configured in web.config.

<object id="licenseGenerator" type="FergusonMoriyama.UmbracoStore.LicenseGen.Licensing.IpLicenseGenerator, FergusonMoriyama.UmbracoStore">
        <property name="EncryptionProvider" ref="encryptionProvider"/>
</object>

Note that the previously defined encryption provider is passed to the generator and is used to encrypt the generated license key. The provided license generator only provides licenses of type IP.

The contents of the license key is entirely up to you. If you are generating an IP based license you may just want to return the IP address so your product can check the contents of the key against the server it is running on.

Define your products

You need to add one or more products to web.config and example defintion is as follows:

<object id="mapDataTypeProduct" type="FergusonMoriyama.UmbracoStore.LicenseGen.Domain.Product, FergusonMoriyama.UmbracoStore">
        <constructor-arg name="id" value="fergusonmoriyama_map_datatype"/>
        <constructor-arg name="key" value="810232dada390212"/>
        <property name="LicenseGenerators">
          <list element-type="FergusonMoriyama.UmbracoStore.LicenseGen.Licensing.LicenseGenerator, FergusonMoriyama.UmbracoStore">
            <ref object="licenseGenerator"/>
          </list>
        </property>
      </object>

The id constructor-arg is the identifier of the product that you use when setting it up in the Umbraco store.

The key constructor arg is the value that is passed to your encryption provider in order to encrypt the license key. You product will also need to know about this key in order to decrypt the information stored in the key - you may wish to try and obfuscate this value to some extent.

Once you have configured your products they'll need to be added to the products list as follows:

<object name="products" type="System.Collections.Generic.List&lt;FergusonMoriyama.UmbracoStore.LicenseGen.Domain.Product>">
        <constructor-arg index="0">
          <list element-type="FergusonMoriyama.UmbracoStore.LicenseGen.Domain.Product, FergusonMoriyama.UmbracoStore">
            <ref object="mapDataTypeProduct" />
          </list>
        </constructor-arg>
      </object>

Storing copies of issued licenses

By default licenses generated by the application are sent back to the Umbraco store which then relays them to the purchaser.

If you wish to store copies of the licenses generated by your application locally then you'll need to implement the LicenseDao interface:

   public interface LicenseDao
    {
        void Create(License l);
    }

Once implemented replace the reference to the dummy implementation with your own in web.config

<object id="licenseDao" type="FergusonMoriyama.UmbracoStore.LicenseGen.Dao.DummyLicenseDao, FergusonMoriyama.UmbracoStore"/>

Note: the default DummyLicenseDao simply dumps the details of generated licenses to a log file.

Reading your product catalog from an alterantive data store

If you wish to define your list of products in a database or alternative data store you'll need to implement the ProductDao interface:

    public interface ProductDao
    {
        Product getProduct(String id);
    }

Once implemented you'll need to replace the default implementation in web.config

<object id="productDao" type="FergusonMoriyama.UmbracoStore.LicenseGen.Dao.MemoryProductDao, FergusonMoriyama.UmbracoStore">
        <property name="Products" ref="products"/>
      </object>