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.