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. Read more in the "CORS on non-public buckets" section below.

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, four operations are supported for the B2 Native API and five for the S3 Compatible API. See below for details.

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 for uploads

You can set up CORS rules to allow b2_upload_file and b2_upload_part calls to be performed from web browsers. See the uploading page to learn more about how uploading works. Keep in mind the following things:

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 63 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 Native API Operations:
  • b2_download_file_by_name
  • b2_download_file_by_id
  • b2_upload_file
  • b2_upload_part
S3 Compatible Operations, one for each supported HTTP method, mapping to the AllowedMethod element in S3’s CORSRule object.
  • s3_delete
  • s3_get
  • s3_head
  • s3_post
  • s3_put

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 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-content-sha1' header to the web page.

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

CORS on non-public buckets

Requests 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 a CORS rule allowing it.

Browsers do not include most headers when doing a CORS preflight. Therefore, when using CORS for downloads on a private bucket, you need to use a download authorization token and include it in the download url as a query parameter, not as a header. Be sure to capitalize only the first letter of 'Authorize', as in the following example:

https://f000.backblazeb2.com/file/buck/my.js?Authorization=3_20181026...dnld

CORS with the S3 Compatible API

The S3 Compatible API supports the PutBucketCors, GetBucketCors, and DeleteBucketCors API calls. For a guide on how to use these API calls, please refer to the AWS CORS documentation.

The accepted format for the calls is the same as the AWS S3 equivalents. Any differences between our implementation are documented on the S3 Compatible API docs page.

Using CORS Rules with the S3 Compatible and B2 Native API

When viewing CORS Rules that are set for the S3 Compatible API via the B2 Native API you will see the following behavior: