DEV Community

Shoichi Okaniwa
Shoichi Okaniwa

Posted on • Originally published at qiita.com

Node.jsで発行したS3の署名付きURLへアップロードすると403エラーになる

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,
});
Enter fullscreen mode Exit fullscreen mode

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,
});
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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,
});
Enter fullscreen mode Exit fullscreen mode

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)