This post was originally intended as an introduction to the license acquisition process. I wanted to describe how every license request looks for those that are interested and that is it. But after I started writing it, I remembered that customers who were interested in what the license request looks like were also interested in writing their own license acquisition proxies. So, this post will be a little bit of everything:
- Description of the license request for every DRM, the format, and the sequence of requests
- Notes on what to expect if you write your own proxy
- Notes on how the playback client (player) usually behaves prior to the license request, and what it expects from the license service/proxy
The License Acquisition
I assume you know about the process already, but, let’s refresh it just in case. To playback the DRM-protected content:
- The Content Decryption Module (CDM) in your browser or Mobile SDK generates the license challenge
- The player makes a license (or a certificate) request to the license acquisition proxy hosted on your side for authentication/authorization
- The proxy generates the Authentication XML (security token)
- The proxy sends the license or a certificate request with the security token to the KeyOS MultiKey Service/Server
- The KeyOS MultiKey Service/Server process the request and generates a license, or a certificate, that it returns to the proxy and the proxy returns it back to the player.
The process itself is simple. Where you may have questions is at the point when you need to write your own license acquisition proxy. This is exactly where the knowledge about the license request comes in handy.
Knowing how to make a correct license request from the proxy to the license service is essential. If done wrong, you won’t get a license that you can return to the player to start the playback.
Dealing With the License Challenge
What is the license challenge? Well, every license requests the player makes is a POST request. Every POST request has a body. The body of the POST license request is what we call a license challenge. One may also call it a payload.
The license challenge is something that is automatically generated by the player. It is not something you compile manually with your hands. The license challenge contains information about the end user's system and is signed to prevent changes in transition.
One thing to remember when dealing with the license challenge is that you must not alter it. The CDM generates it according to the DRM vendor’s specification, and if altered it usually becomes corrupted.
The PlayReady License Request
Let us start with PlayReady. The PlayReady license request is a POST request with an XML body. The example below (truncated) is what the CDM usually generates for the player to send to the KeyOS MultiKey License Service/Server or the license acquisition proxy on your side:
The response that the KeyOS MultiKey Service/Server produce is an XML and may look as follows (truncated):
Modern players do not require custom development from you to support PlayReady. You simply set the license acquisition URL and viola; it works.
The Widevine License and Certificate Requests
The Widevine license request is a bit tricky. In some cases, for example, when the HTML5 player is used to acquire a license, the client will make two requests.
The first request will be after a Widevine public certificate that will be used by the CDM to generate an actual license challenge. The certificate request is easy to spot – it is a POST request which has only two bytes in its body:
If you write your own license proxy, you must not forget to implement logic to process such requests. For example, here is how it may look in Node.js using an express server:
The axios.post in the above example sends the payload forward to the KeyOS MultiKey Service/Server that in turn returns the certificate.
Note: It is possible to cache the Widevine certificate or hardcode it into the player directly. If you do that instead of requesting the certificate from the DRM provider, make sure to update the Widevine certificate regularly as it may change on the DRM provider side.
After the player gets the Widevine certificate, it generates a license request which is a POST with a binary body. Here is the part of it in HEX:
The response will also be binary data, for example:
Note: be careful when working with different services like Lambda, from AWS, for example. It must be properly configured to work correctly with the binary data, or you may end up getting the base64 encoded value from your license acquisition proxy and the player will fail to process the license as it expects the license to be in binary format.
The FairPlay License and Certificate Requests
Like Widevine, players that support FairPlay will make a request for a certificate prior to making the license request. The good news is that you don’t need to process it in any way in your proxy. The player is configured in such a way that the URL for the certificate is different from the URL of the license services. It is not the case with Widevine setup when the player will make the request after the certificate and the license to the same URL.
Note: It is possible to cache the Fairplay certificate, or hardcode it into the player directly. If you do that instead of requesting the certificate from the DRM provider, make sure to update the Fairplay certificate regularly as it may change on the DRM provider side.
The FairPlay license request is a POST request with text as a body. The tricky part with FairPlay is to remember that there is no strict specification about how the license request must look like. Every DRM provider may implement its own format.
In the case of KeyOS MultiKey Service/Server, we expect the POST request with the following text as a body:
<spc> - is the Server Playback Context, which is delivered to the player by the CDM. The SPC MUST be base64 encoded and MUST NOT be URL encoded. On the code level, the SPC value is usually provided in the event in your player prior to the license request. You can capture the even and work with the SPC as needed. You don’t need to generate this value yourself.
<assetId> - is the value from the m3u8 manifest, which is usually located inside the URI property of the EXT-X-KEY. The length of the assetId in a request MUST be 32 symbols. On the code level, the assetId is usually provided as the parameter in one of the events that are called prior to the license request in your player. In most cases, you don’t need to specifically parse the manifest to get this value.
The player automatically extracts the assetId from either the master or the variant m3u8 manifest, from the EXT-X-KEY or EXT-X-SESSION-KEY directives. For example:
The assetId in the above example is “71b3f031667e417e9d924535c67ce02b” (the value from the URI property that comes immediately after the “skd://”), and is 32 symbols long. Any other parameters that may come after the actual assetId must be dropped.
The sample of the license challenge is below (truncated):
The response is a base64-encoded string. For example (truncated):
Modern players allow you to override license acquisition methods, or catch events that are related to SPC or assetId extraction, or the license acquisition.
You can use these methods to format your license acquisition requests’ body i.e. the license challenge. Once the Fairplay license request is sent, the player will expect the license response to be processed. It may allow you to override the method that does that, or do it automatically. Also, depending on the player, it may expect a license as base64-encoded string, or binary data.
The KeyOS MultiKey Service/Server returns the license in base64-encoded format. If your player doesn’t support that, override the license acquisition function and base64 decode the data returned by the KeyOS MultiKey Service/Server to get the license in binary format.
If you have any questions or issues during the license request, just create a support ticket in our support system and we will be glad to help you.