Understanding CORS

In this topic, you will learn about CORS and constraints built into the Web regarding cross-origin referencing of assets such as videos, images, and scripts.

Overview

Cross-origin resource sharing (CORS) is a mechanism that allows a web page to make requests to another domain other than the one from which the page was served. Normally cross-domain requests would otherwise be forbidden by web browsers. CORS defines a way domains can interact to determine whether or not to allow a cross-origin requests.

CORS and Brightcove

There are three instances when CORS must be used with Brightcove services/products:

  1. Captions for videos: The file that contains captions for a video can be stored on a non-Brightcove domain. Since the video itself will be served from a Brightcove domain, this will cause cross-domain issues.
  2. Brightcove Player and HLS: The Brightcove Player's HLS plugin uses AJAX requests to retrieve the HLS video's manifest and individual segments. Since these HLS resources can be stored on any Internet accessible domain, it is likely these resources will be served from a different server (typically a CDN domain) than from the Brightcove domain that served the player. This will again cause cross-domain issues.
  3. Video Still and Thumbnail Images: for capturing video still and thumbnail images in Studio, the video rendition must be served with CORS headers (which should be enabled on most of Brightcove's house CDNs by default); if you have a custom CDN, or one we haven't updated yet, image capture will not work

Solutions

The solution that Brightcove is using at this time involves configuring an Access-Control-Allow-Origin header in the CDN origin server’s configuration file. It’s important to note that since different CDN partners use different server solutions to deliver their content, the header information below is offered as an example, and not as a drop-in code snippet.

Brightcove has had success with the following header directive for in-house CDN server's properties:

<FilesMatch ".(vtt|xml)$">
              Header set Access-Control-Allow-Headers: X-Requested-With
              Header add Access-Control-Allow-Origin: https://admin.brightcove.com
          </FilesMatch>

The following provides brief explanations of the directive:

  • <FilesMatch ".(vtt|xml)$">: This conditional sets the Access-Control-Allow-Origin header only on vtt or xml files. Testing has confirmed that this header is not sent with images or other http-delivered content.
  • Header set Access-Control-Allow-Headers: X-Requested-With: This header is required for the Access-Control-Allow-Origin header to work, since the request the player is making is an XmlHttpRequest.
  • Header add Access-Control-Allow-Origin: https://admin.brightcove.com: This is the access control header itself to allow content from the indicated domain.

Enabling CORS on Apache

You can set a header in the configuration of Apache servers to enable CORS. Place the following in the appropriate .conf file:

Header set Access-Control-Allow-Origin "*"

In the example above the asterisks acts as a wild card and allows access to all domains. The wildcard can also be replaced by one specific domain. That generally won't work for Brightcove players, because in many cases assets will reside on multiple domains. You can implement other solutions to limit access to a specific whitelist of acceptable domains.

BYO CDN

If you are a customer with a BYO CDN and having cross-domain issues, you should contact your CDN for help in configuring CORS for your account. Here are the settings we recommend:

  • Access-Control-Allow-Headers: X-Requested-With
  • Access-Control-Allow-Origin: *
  • file formats: m3u8 m3u ts xml dfxp vtt mpd m4f mp4 jpg png

Token authorization requirements

In the case where token authorization is required alterations need to be made to the solution above. In the case of token authorization, the CORS security model specifically disallows the use of the * character as a value for the Access-Control-Allow-Origin response header. In addition, the Access-Control-Allow-Credentials response header is required, and must be set to true.

An updated header directive for token authorization is:

<FilesMatch ".(m3u8 | m3u | ts)$">
        # with AJAX withCredentials=true (cookies sent, SSL allowed...)
        SetEnvIfNoCase ORIGIN (.*) ORIGIN=$1
        Header set Access-Control-Allow-Origin "%{ORIGIN}e"
        Header set Access-Control-Allow-Credentials "true"
        RewriteEngine On
        RewriteCond %{REQUEST_METHOD} OPTIONS
        RewriteRule ^(.*)$ $1 [R=200,L,E=HTTP_ORIGIN:%{https:ORIGIN}]
  </FilesMatch>

The following points detail the differences from the earlier solution:

  • The directive queries the incoming request for the presence of an Origin header, and if that header is present (it usually is), sets its value to a variable called ORIGIN: SetEnvIfNoCase ORIGIN (.*) ORIGIN=$1
  • The Access-Control-Allow-Origin response header value is set to the value of the ORIGIN variable just created: Header set Access-Control-Allow-Origin "%{ORIGIN}e"
  • The Access-Control-Allow-Credentials header must be set to true: Header set Access-Control-Allow-Credentials "true"

HLS and CORS

In some environments (such as Amazon S3) you can specify a CORS configuration for HLS. The following configures CORS to allow HLS playback.

<CORSConfiguration>
      <CORSRule>
      <AllowedOrigin>*</AllowedOrigin>
      <AllowedMethod>GET</AllowedMethod>
      </CORSRule>
</CORSConfiguration>

For further information specific to Amazon S3 see Enabling Cross-Origin Resource Sharing.

Although tangential to CORS, the client browser needs to accept all session cookies for Token Authorized HLS content delivery to work properly. While some client browsers, such as Google Chrome and Mozilla Firefox, accept session cookies by default, other browsers, such as Internet Explorer, do not so this option must be enabled by the user.