I'm working of a S3 Navigator and trying to use Backblaze B2's S3-compatible API in my Angular application to authenticate and list buckets using the AWS SDK's S3Client. While this code works perfectly with other S3-compatible providers like Wasabi and IDrive E2, I am encountering a CORS error when attempting to interact with Backblaze B2. Despite configuring CORS rules to "Share everything in this bucket with every origin", the error persists.
Below is my code that authenticate s3-compatible account and list buckets in account. code is working fine in case of Wasabi and I-Drive E2 but not in case of BackBlaze B2:
Code:
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';
async authenticateAccount(
endpoint: string,
accessKeyId: string,
secretAccessKey: string
) {
console.log('s3 client used');
if (!/^https?:\/\//i.test(endpoint)) {
endpoint = `https://${endpoint}`;
}
try {
new URL(endpoint);
} catch (error) {
console.error('Invalid endpoint URL:', endpoint);
throw new Error('Invalid endpoint URL');
}
console.log("entered url is", endpoint);
const s3 = new S3Client({
region: 'us-east-005', //buckets are in this region in backblazeB2
endpoint,
credentials: {
accessKeyId,
secretAccessKey,
},
forcePathStyle: true,
});
try {
const command = new ListBucketsCommand({});
const response = await s3.send(command);
return response;
} catch (error) {
console.error('Error getting bucket information:', error);
throw error;
}
}
Error I got:
Access to fetch at 'https://s3.us-east-005.backblazeb2.com/?x-id=ListBuckets' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I have checked my Endpoint, Access Key ID and Secret Key ID multiple times they are correct as the same credentials works when used on s3 Browser.
There are a couple of things going on here. The first is that the S3 operations you can specify in a Backblaze B2 CORS rule are restricted to the following (see the docs):
If you need to perform operations such as listing buckets from the browser with Backblaze B2, please submit an idea to our product portal (click the red plus sign, lower left) and we can look at adding them to CORS rules.
Another issue in your implementation is that rendering long-lived credentials such as the application key and its ID (accessKeyId
and secretAccessKey
in S3 parlance) into the browser is very dangerous - if they are intercepted then an attacker has a long window of opportunity to access your data. See the recommendation in the Amazon S3 docs here.
You should keep these credentials on the server and render pre-signed URLs into the page if you want to access storage directly from the browser. This won't solve your CORS issue, but it is best practice when working with any cloud object storage system.