Presigned URLs are a great way to securely allow client applications to upload files to S3. In addition, using a post presigned URL enables you to create restrictions on the uploads, such as how long the client has to upload a file, the name of the file, etc.
Creating a Presigned URL
Since some AWS regions don’t default to using Sig v4 when you create an instance of the AWS S3 client. Because of this, you’ll want to make sure you set the signatureVersion
configuration property to v4
.
const s3 = new AWS.S3({signatureVersion: 'v4'});
Creating a presigned URL is pretty easy; call getSignedUrl
, pass in the type of URL you need, and give it some details about the upload.
const url = s3.getSignedUrl('putObject', {
Bucket: "upload-test",
Key: "some/object/key.txt",
Expires: 100
});
You’ll need to run this code from an environment that has permission to upload to the bucket. For example, if you’re running this code from a lambda that you’re calling from AppSync, you need to make sure the lambda’s IAM Role has s3:putObject
permission for the resource arn:aws:s3:::upload-test/*.
Upload a File
Uploading a file couldn’t be easier. Just put it to the provided URL and send a file in the body. All required parameters are provided in the URL as query parameters.
import Axios from "axios";
const uploadFile = async (presignedUrl: string, file: File) => {
const result = await Axios.put(presignedUrl, file)
.catch(error => console.error(error.response.data, {request: error.request}));
console.info(result.data);
return result.data;
};
Conclusion
I hope you found this helpful and were encouraged to secure your S3 Buckets a little better using this method. Feel free to reach out to me on Twitter if you have any questions.
Cover Photo by Wonderlane on Unsplash