0

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.

AG_HIHI
  • 1,705
  • 5
  • 27
  • 69
  • That makes sense. But, it still means that I have to go through the entire app, and wherever there's an image in the response, some work (your approach or mine) needs to be done. Besides, your approach seems to require even more work especially given that the expiration date for the presigned url will be short for security reasons. So basically, I will always have to regenerate it so it's the same thing as in my approach with the extra work of checking expiry date and storing the original S3 URI in the database. – AG_HIHI Nov 20 '22 at 06:33
  • Meant saving the signed url in the database* – AG_HIHI Nov 20 '22 at 08:02

0 Answers0