In which stage should I generate signed urls to load S3 bucket objects in an app?

104 Views Asked by At

I am using S3 to store images in my app.
This is the function that generates the signed url that the user can use to upload an image:

 const key = `images/${Date.now()}.jpeg`;
    s3_config
      .getImageSignedUrl(key)
      .then((url) => {
        res.status(200).send({ key, url });
      })
      .catch((error) => {
        res.status(500).send({
          message: "There was an error generating pre-signed url.",
        });
      });

So after the image is uploaded, the image url will look like this:

https://BUCKET_NAME.s3.amazonaws.com/images/1667119739573.jpeg

Now, in order to make the images only accessible on the website, I will also use a signed-url.

This way when someone uses the direct link:

https://BUCKET_NAME.s3.amazonaws.com/images/1667119739573.jpeg

He will get AccessDenied error.

And only users within the app, will be able to access the images using the signed urls.

This is how I generated the signed url for loading an image:

var getImageReadSignedUrl = async function (key) {
  return new Promise((resolve, reject) => {
    s3.getSignedUrl(
      "getObject",
      {
        Bucket: AWS_BUCKET_NAME,
        Key: key,
        Expires: 300,
      },
      (err, url) => {
        if (err) {
          reject(err);
        } else {
          resolve(url);
        }
      }
    );
  });
};

And if I feed it an image key:

getImageReadSignedUrl("images/1667119739573.jpeg");

It will generate a signed url that will allow the user to access the private image:

https://BUCKET_NAME.s3.eu-west-3.amazonaws.com/images/1667119739573.jpeg?X-Amz-Algorithm=xxxxxxxxxxxxxxxxx&X-Amz-Credential=xxxxxxxxxxxxxxxxxxxx9%2Feu-xxxx-3%2Fs3%2Faws4_request&X-Amz-Date=202211xxxxxxxx35Z&X-Amz-Expires=300&X-Amz-Signature=5ab0exxxxxxxxxxxxxxxxxx8dc401dc7fxxxxxxxxa5124&X-Amz-SignedHeaders=host

Now, so far so good. Everything works perfectly as intended.

My problem is when or how or where exactly I should use the function getImageReadSignedUrl.

Since in the database, I am saving the direct link to the image:

https://BUCKET_NAME.s3.amazonaws.com/images/1667119739573.jpeg

When the user is using the app, he will receive that url.
And it will be using inside the img html tag, to render the image.

Now, the question is, should I use getImageReadSignedUrl everytime before there's an image url in the data that's sent back to the user and send the signed url instead?

Even though, this makes sense, this means that I will have to go through the entire app in the backend and call that function, everytime there's an image to be sent back to the user.

Is there another approach that makes more sense and is not as tedious as this?


FYI, I am using the MERN stack and an EC2 instance. Thank you.

0

There are 0 best solutions below