Handling 403 Errors When Uploading to S3 Signed URLs with Node.js
I encountered challenges uploading files to Amazon S3 using signed URLs with Node.js. So, here’s a rundown to avoid the same issues in the future.
I referred to this article on generating signed URLs with Node.js:
{AWS(CloudFront+S3)+Node.js} Delivering Private Content Using Signed URLs
Successfully Generated Download Signed URLs
Generating signed URLs for downloading worked smoothly with the following code:
import AWS from 'aws-sdk';
// AWS authentication details
// Create S3 instance
const s3 = new AWS.S3();
// Generate download URL
const downloadUrl = await s3.getSignedUrl('getObject', {
Bucket: 'your-bucket-name',
Key: 'your-object-name',
Expires: 60,
});
Encountering Issues with Upload Signed URLs
Using a similar approach, I generated upload signed URLs, which were created successfully.
import AWS from 'aws-sdk';
// AWS authentication details
// Create S3 instance
const s3 = new AWS.S3();
// Generate upload URL
const uploadUrl = await s3.getSignedUrl('putObject', {
Bucket: 'your-bucket-name',
Key: 'your-object-name',
Expires: 60,
});
However, when attempting to upload a file using the generated URL, I received a 403 status code. The response body looked like this:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<AWSAccessKeyId>hoge</AWSAccessKeyId>
<StringToSign>hoge</StringToSign>
<SignatureProvided>hoge</SignatureProvided>
<StringToSignBytes>hoge</StringToSignBytes>
<RequestId>hoge</RequestId>
<HostId>hoge</HostId>
</Error>
In short, it indicated an issue with the signing method.
Utilizing Signature Version 4
After further investigation, I discovered an issue:
Node.js pre-signed URL for PUT response is 'signature does not match'
As per this issue, use signature version 4 when generating the URL.
// Create S3 instance
const s3 = new AWS.S3({
signatureVersion: 'v4',
});
// Generate upload URL
const uploadUrl = await s3.getSignedUrl('putObject', {
Bucket: 'your-bucket-name',
Key: 'your-object-name',
Expires: 60,
});
By testing uploads with the above code, I successfully uploaded files!
Conclusion
I'm relieved to have resolved this issue. Special thanks to the following articles for their clear explanations:
Top comments (0)