aws-sdk .SharedIniFileCredentials profile: 'wasabi' browser alternative

536 Views Asked by At

I am trying to implement S3 file hosting at wasabi using the examples from their docs. While setting up credentials with SharedIniFileCredentials works great in Node, I would need to use the same functionality inside the browser.

Here, I get the following error

aws_sdk__WEBPACK_IMPORTED_MODULE_1___default(...).SharedIniFileCredentials is not a constructor

This is my code (that runs great inside node, but throws an error inside a React component):

import AWS from 'aws-sdk';

export const createS3Client = (): AWS.S3 => {
  const credentials = new AWS.SharedIniFileCredentials({ profile: 'wasabi' });
  AWS.config.credentials = credentials;

  AWS.config.credentials.accessKeyId = process.env.NX_WASABI_KEY;
  AWS.config.credentials.secretAccessKey = process.env.NX_WASABI_SECRET;

  AWS.config.region = process.env.NX_WASABI_REGION;
  const ep = new AWS.Endpoint(process.env.NX_WASABI_ENDPOINT);
  const s3 = new AWS.S3({ endpoint: ep });
  return s3;
};

export const getFile = async (key: string): Promise<Buffer> => {
  const s3 = createS3Client();
  const params = {
    Bucket: process.env.NX_WASABI_BUCKET,
    Key: key,
  };

  const data = await s3.getObject(params).promise();
  return data.Body as Buffer;
};

The main reason why I am trying to do this is because I want to load images stored inside a bucket that are not publicly available into a FE (React) component.

This is the component in question:

import { useEffect, useState } from 'react';
import { getFile } from '../../lib/wasabi';

import Image from 'next/image';

import styles from './PaletteImage.module.scss';

interface Props {
  name: string;
  source: string;
}

const PaletteImage = ({ name, source }: Props) => {
  const [isLoading, setIsLoading] = useState(true); // component needs to load image data on mount
  const [error, setError] = useState<string>();
  const [base64, setBase64] = useState<string>();

  useEffect(() => {
    const parseImage = async () => {
      try {
        const buffer = await getFile(source);
        setBase64(buffer.toString('base64'));
      } catch (e) {
        setError(e.message);
      } finally {
        setIsLoading(false);
      }
    };

    parseImage();
  }, []);

  return (
    <div className={styles.imageContainer}>
      {isLoading ? (
        'loading'
      ) : error ? (
        error
      ) : (
        <Image
          alt={name}
          layout="fill"
          objectFit="contain"
          objectPosition="left top"
          src={`data:image/jpeg;base64, ${base64}`}
        />
      )}
    </div>
  );
};

export default PaletteImage;

Thanks for the help.

1

There are 1 best solutions below

0
On

You will need to use an alternative to AWS.SharedIniFileCredentials since the browser scripts of the AWS JavaScript SDK do not support it and the browser version of the SDK can't also get access to AWS.SharedIniFileCredentials that is meant to retrieve credentials from the local file system.

Options available include CognitoIdentityCredentials or Web Federated Identity. See: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-browser.html

I suggest you refer to the following documentation for the AWS Javascript SDK:

https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/js-sdk-dv-v2.pdf#setting-credentials-browser

Cheers