Third Party Licensing

What is Third Party Licensing?

The Third Party Licensing feature allows you to internally take control of Allowing or Denying the use of your Player Key. Normally Bitmovin Players will validate a License call against a given License Key by comparing the requesting Domain (web), App Package (Android), Bundle ID (iOS), or Channel ID (Roku) against what you have Allow-Listed inside your Bitmovin Dashboard.

However, with Third Party Licensing we pass that control back to you. This may be useful scenarios such as:

  • Allowing Partners to embed your content on their site or app
  • Real time control and logging of your Player Licensing requests

Compatibility

Third Party Licensing is applied to a specific License Key which can be used by our Web, Android, iOS, and Roku Players.

How does it work?

The Third Party Licensing workflow consists of the player first making the license request to our Licensing platform. Then the Bitmovin Licensing Platform passes that license request to the HTTPS endpoint that you specify in the Bitmovin Dashboard for your License. Your endpoint POST method call which contains a pre-defined JSON payload structure shown in the next section and then Accept or Deny the request based on the HTTP response we get from the POST method.

Data passed to your License Server

The licensing HTTPS POST call will contain the following JSON Payload. There are 3 standard fields - domain, key, and version included in all requests, along with an optional customData field.

  • domain - String containing the origin Domain, Package Name, Bundle Identifier, or Channel ID
  • key - String containing the License Key. This may be useful if you use the same endpoint for multiple Keys enabled with 3rd Party Licensing
  • version - String containing the Player version.
  • customData - Optional JSON Object containing key/value pairs which can contain arbitrary data. This data is set by calling the PlayerApi.setAuthentication method.
    Note: This field only applies to our HTML5-based Web Player.

Your licensing endpoint's Allow/Deny logic can you use any combination of the above data fields to determine whether or not to Allow licensing request. For example, if you want to enable Partner content by simply checking the domain you could just validate against the domain field.

For our HTML5 Player, we also allow you can enable more complex checks by requiring some arbitrary data(like a thirdPartyKey for example) to be passed in the customData field.

{
    "customData": {
        "param2": "data2",
        "thirdPartyKey": "key1"
    },
    "domain": "dummydomain.com",
    "key": "your_player_licensekey",
    "version": "player_version"
}

Endpoint responses

Your licensing server needs to respond with either a 2xx code, 4xx code, or 5xx code as described below You can also return arbitrary customData in the response as well that will be passed to the client.

  • HTTP code 2xx -> Allow License
  • HTTP code 4xx -> Deny License
  • HTTP code 5xx -> Allow/Deny based on configuration in your Bitmovin Dashboard
  • Timeout -> Response Timeout and Default Action based on configuration in your Bitmovin Dashboard.

Response codes 2xx will explicitly Allow while response codes 4xx will explicitly Deny. You can also set the default behavior for Internal Server Error codes 5xx as well as the default behavior if no response is given within your configured timeout.

Third Party Licensing is controlled at the Player Key level, so once enabled, ALL requests for a given key will be routed to the endpoint that you provided. If you are using 3rd Party Licensing to enable Partners to use your player/content, It is good practice to create secondary Player licenses to be used along with this licensing strategy to isolate Partner licensing from your own Production Player licensing.

Example Third Party License Server Implementation

This tutorial will be based on the supplemental sample content hosted in our Github repos here - https://github.com/bitmovin/licensing-demo

Creating The Server

You can host your Licensing endpoint however you want - For example, a Java Servlet, AWS API Gateway + Lambda, NodeJS server, etc… For this example we will setup a simple Java Servlet that will look for an arbitrary key called thirdPartyKey to passed as a key/value in the customData field. The servlet will return a 200 if a valid thirdPartyKey is provided and will return a 400 code if not. In case of an Exception being raised the servlet will return a 500 code. In this example our Servlet will also return a customData JSON payload via Key/Value pairs.

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class LicenseServerServlet extends HttpServlet {
    private final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        LicenseRequest licenseRequest;
        boolean allowLicense;
        Map<Object, Object> customData = new HashMap<Object, Object>();
        try {
            licenseRequest = gson.fromJson(request.getReader(), LicenseRequest.class);
            String thirdPartyKey = (String) licenseRequest.getCustomData().get("thirdPartyKey");
            if (thirdPartyKey == null || !getLicenses().containsKey(thirdPartyKey)) {
                customData.put("msg", "No valid thirdPartyKey provided");
                sendDenyResponse(response, customData);
                return;
            }
            allowLicense = getLicenses().get(thirdPartyKey);
            if (!allowLicense) {
                customData.put("msg", "thirdPartyKey: " + thirdPartyKey + " not allowed");
                sendDenyResponse(response, customData);
                return;
            }
            customData.put("domain", licenseRequest.getDomain());
            sendAllowResponse(response, customData);
        } catch (Exception e) {
            customData = new HashMap<Object, Object>();
            customData.put("msg", "Internal Server Error");
            sendErrorResponse(response, customData, e.getMessage());
        }
    }
    private void sendAllowResponse(HttpServletResponse response, Map<Object, Object> customData) throws IOException {
        customData.put("message", "thirdPartyKey was approved.");
        response.setStatus(200);
        response.setContentType("application/json");
        response.getWriter().write(gson.toJson(customData));
    }
    private void sendDenyResponse(HttpServletResponse response, Map<Object, Object> customData) throws IOException {
        customData.put("message", "thirdPartyKey was denied.");
        response.setStatus(400);
        response.setContentType("application/json");
        response.getWriter().write(gson.toJson(customData));
    }
    private void sendErrorResponse(HttpServletResponse response, Map<Object, Object> customData, String error) throws IOException {
        customData.put("message", error);
        response.setStatus(500);
        response.setContentType("application/json");
        response.getWriter().write(gson.toJson(customData));
    }
    private Map<String, Boolean> getLicenses() {
        Map<String, Boolean> licenses = new HashMap<String, Boolean>();
        licenses.put("12345", true);
        licenses.put("67890", false);
        return licenses;
    }
}
class LicenseRequest {
    String domain;
    String key;
    String version;
    Map<Object, Object> customData;
    Map<Object, Object> getCustomData() {
        return this.customData;
    }
    String getDomain() {
        return this.domain;
    }
    String getKey() {
        return this.key;
    }
    String getVersion() {
        return this.version;
    }
}

Now all you need to is to do is host this Java Servlet.

Note: It's important to consider your average and peak player usage when hosting your Third Party Licensing endpoint and plan your capacity/redundancy/availability of your hosting accordingly. It is also important to consider how you want Bitmovin's License platform to handle both timeouts and server errors (5xx responses) from your endpoint - This is configurable and shown in the next section.

Enabling Third Party Licensing in the Bitmovin Dashboard

Let's head over to the Bitmovin Dashboard to configure our Player License for Third Party Licensing. Once logged into your Dashboard, Select PLAYER > Licenses from the left-hand menu and Select the License you want to enable.

  1. In the Third Party Licensing modal, enter your hosted License API endpoint into the Server Url input.
  2. Set your response timeout in milliseconds - Maximum of 2000 milliseconds
  3. Set your Default (Allow or Deny) for Error Action (5xx server response)
  4. Set your Default (Allow or Deny) for Timeout.

  1. Lastly, click the Enable Button.

Your License is now enabled for Third Party Licensing and ALL licensing requests for the given Key will be routed through this flow.

Player Configuration

To round-off our above example, let’s configure a Bitmovin Web Player example that will set the example thirdPartyKey field that our sample Servlet expects.

let playerConfig = {
    key: "<Player License>",
}
let source = {
    hls: '...',
}
let player = new bitmovin.player.Player(document.getElementById("player"), playerConfig);
player.setAuthentication({
    thirdPartyKey: '12345'
})
player.load(source).then(() => {
    console.log('Source loaded successful');
});