CORS: Cross-Origin Resource Sharing

Web browsers generally limit a web page's access to content from other sites. B2 supports Cross-Origin Resource Sharing (CORS) to allow users to lift those restrictions.

Web browsers group pages by their 'origin', which is the combination of their protocol (eg. 'http' or 'https'), their hostname (eg. 'f001.backblazeb2.com'), and their port number (usually 80 or 443 for http and https). While images can be embedded from any origin, by default, Javascript can usually only use XMLHttpRequests to get content from the same origin as the HTML page that included the script. Similarly, by default, WebGL will only load textures from the same origin.

B2 supports the standard Cross-Origin Resource Sharing (CORS) mechanism to allow B2 customers to share the content of their buckets with web pages hosted outside of B2. With CORS, before making a non-simple cross-origin request, a browser makes a "preflight" request to ask the server if it's ok to make the cross-origin request. By default, the B2 servers will say "no" to preflight requests. Adding CORS rules to your bucket tells B2 which preflight requests to approve.

Note that CORS does not replace normal B2 authorization mechanisms. Requests will still need to present normal B2 authorization tokens to download content from non-public buckets. Additionally, B2 will deny CORS preflight requests that use the account authorization token returned by b2_authorize_account. Only more restricted authorization tokens are allowed, such as those returned by b2_get_download_authorization. (This restriction exists because you shouldn't send your real account credentials or authorization to web browsers!) The authorization token returned by b2_get_download_authorization is only valid for b2_download_by_name. Together these restrictions mean that you cannot yet b2_download_by_id from a private bucket even with CORS rule allowing it.

When a CORS preflight or cross-origin download is requested, B2 evaluates the CORS rules on the file's bucket. Rules may be set at the time you create the bucket with b2_create_bucket or updated on an existing bucket using b2_update_bucket.

CORS rules only affect B2 operations in their "allowedOperations" list. Every rule must specify at least one in their allowedOperations. So far, only the two download operations are supported.

You may add up to 100 CORS rules to each of your buckets. Each rule must be less than 1000 bytes long. (A rule's size in bytes is computed by adding up the byte lengths of the UTF-8 representation of each string in corsRuleName, allowedOrigins, allowedOperations, allowedHeaders, and exposeHeaders.)

B2 uses the first rule which matches the request. A CORS preflight (OPTIONS) request matches a rule if the origin header matches one of the rule's allowedOrigins, if the operation is in the rule's allowedOperations, (case-sensitive) and if every value in the Access-Control-Request-Headers is in the rule's allowedHeaders. A non-preflight request (GET or POST) matches a rule if the origin header matches one of the rule's allowedOrigins and if the operation is in the rule's allowedOperations.

CORS Rule Structure

Each CORS rule may have the following parameters.

corsRuleName

required

A name for humans to recognize the rule in a user interface. Names must be unique within a bucket. Names can consist of upper-case and lower-case English letters, numbers, and "-". No other characters are allowed. A name must be at least 6 characters long, and can be at most 50 characters long. These are all allowed names: myPhotosSite, allowAnyHttps, backblaze-images. Names that start with "b2-" are reserved for Backblaze use.

allowedOrigins

required

A non-empty list specifying which origins the rule covers. Each value may have one of many formats:
  • The origin can be fully specified, such as http://www.example.com:8180 or https://www.example.com:4433.
  • The origin can omit a default port, such as https://www.example.com.
  • The origin may have a single '*' as part of the domain name, such as https://*.example.com, https://*:8443 or https://*.
  • The origin may be 'https' to match any origin that uses HTTPS. (This is broader than 'https://*' because it matches any port.)
  • Finally, the origin can be a single '*' to match any origin.
If any entry is "*", it must be the only entry. There can be at most one "https" entry and no entry after it may start with "https:".

allowedOperations

required

A list specifying which operations the rule allows. At least one value must be specified. All values must be from the following list. More values may be added to this list at any time.
  • b2_download_file_by_name
  • b2_download_file_by_id

allowedHeaders

optional

If present, this is a list of headers that are allowed in a pre-flight OPTIONS's request's Access-Control-Request-Headers header value. Each value may have one of many formats:
  • It may be a complete header name, such as x-bz-content-sha1.
  • It may end with an asterisk, such as x-bz-info-*.
  • Finally, it may be a single '*' to match any header.
If any entry is "*", it must be the only entry in the list. If this list is missing, it is be treated as if it is a list with no entries.

exposeHeaders

optional

If present, this is a list of headers that may be exposed to an application inside the client (eg. exposed to Javascript in a browser). Each entry in the list must be a complete header name (eg. "x-bz-content-sha1"). If this list is missing or empty, no headers will be exposed.

maxAgeSeconds

required

This specifies the maximum number of seconds that a browser may cache the response to a preflight request. The value must not be negative and it must not be more than 86,400 seconds (one day).

The rule below allows downloads, including range requests, from any https origin and will tells browsers that it's ok to expose the 'x-bz-' headers to the web page.

[
    {
      "corsRuleName": "downloadFromAnyOrigin",
      "allowedOrigins": [
        "https"
      ],
      "allowedHeaders": ["range"],
      "allowedOperations": [
        "b2_download_file_by_id",
        "b2_download_file_by_name"
      ],
      "exposeHeaders": ["x-bz-*"],
      "maxAgeSeconds": 3600
    }
]