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 is not supported for most B2 APIs, so you must perform them in your server, not in a web page. For uploading, this includes calls such as b2_authorize_account, b2_get_upload_url, b2_start_large_file, b2_get_upload_part_url, and b2_finish_large_file.
- Your code is responsible for retrying when uploads don't work immediately.
- The upload URLs and upload authTokens that are returned by b2_get_upload_url and b2_get_upload_part_url can be used to upload to any path in the bucket, so be sure you trust the application and users you give them to.
- To allow b2_upload_file, you will need to add some headers to "allowedHeaders" in your CORS rule, including "authorization", "X-Bz-File-Name", and "X-Bz-Content-Sha1".
- To allow b2_upload_part, you will need to add some headers to "allowedHeaders" in your CORS rule, including "authorization", "X-Bz-Part-Number", and "X-Bz-Content-Sha1".
- You may choose to allow other headers, for instance ones that start with "X-Bz-Info-".
CORS Rule Structure
Each CORS rule may have the following parameters.
corsRuleName
required
allowedOrigins
required
- 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.
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_delete
- s3_get
- s3_head
- s3_post
- s3_put
allowedHeaders
optional
- 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.
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:
- When “null” is set for MaxAgeSeconds through the S3 PutBucketCors API, the CORS rule returned from the B2 Native API will return “5” for MaxAgeSeconds.
- A name for a CORS Rule in the S3 Compatible API is automatically generated to allow it to be displayed in the B2 Native API.
- Modifications to CORS Rules in the B2 Native API via the S3 Compatible API are forbidden. These can only be changed via the B2 Native API.
- A Get Bucket Cors call to the S3 Compatible API will not return any CORS Rules set for the B2 Native API.