Signed PUT Url for NodeJS

December 10, 2017 845 views
Node.js

I heard you guys only support v2 for putObject signed urls. Which node.js clients should I use to create a signed url so I can upload files on the browser?

1 comment
2 Answers

Support for v4 pre-signed URLs is in the works, but you can use v2 signatures with the AWS SDK as well. Depending on the version of the SDK you have installed, it maybe in use by default. (The latest version should when using a custom endpoint. Some older versions used v4 by default everywhere, but this change was reverted in version 2.152.0)

If needed, you can force the signature version when configuring your client:

const s3 = new AWS.S3({
    endpoint: spacesEndpoint,
    accessKeyId: 'YOURACCESSKEY',
    secretAccessKey: 'YOURSECRETKEY',
    signatureVersion: 'v2'
});

Here's a quick example for generating a pre-signed putObject URL with a v2 signature:

const AWS = require('aws-sdk')

const spacesEndpoint = new AWS.Endpoint('nyc3.digitaloceanspaces.com');
const s3 = new AWS.S3({
    endpoint: spacesEndpoint,
    accessKeyId: 'YOURACCESSKEY',
    secretAccessKey: 'YOURSECRETKEY',
    signatureVersion: 'v2'
});

var space = 'my-space-name'
var key = 'my-file-name'
var expireSeconds = 60 

s3.getSignedUrl('putObject', {
    Bucket: space,
    Expires: expireSeconds,
    Key: key
}, function (err, url) {
    console.log(url);
});
  • @asb thank you for the reply. When I try using this code on the latests aws-sdk I get an error saying only v3 and v4 support signature urls. Is there a specific version you are using?

    • Hey @vallelungabrian! I currently have 2.169.0 installed which should be the latest version. Can you share the exact error message you're seeing?

      • I was able to generate the signed url fine with that version but when I try uploading the file I get this error:

        <Error>
          <Code>SignatureDoesNotMatch</Code>
          <RequestId>tx00000000000000002e194-005a30fe87-ed75a-nyc3a</RequestId>
          <HostId>ed75a-nyc3a-nyc</HostId>
        </Error>
        

        for this url

        https://doppler-staging.nyc3.digitaloceanspaces.com/localhost/app_1/model_18/tensorflow?AWSAccessKeyId=NX7JFRSPAOGW4HC3BTIU&Content-Type=application%2Foctet-stream&Expires=1513160347&Signature=ZpKBhVDPTWVKCIaQ5VlJ8rI5ZUU%3D&x-amz-acl=private
        
        • Looking at the docs for getSignedUrl, there is this important note:

          Not all operation parameters are supported when using pre-signed URLs. Certain parameters, such as SSECustomerKey, ACL, Expires, ContentLength, or Tagging must be provided as headers when sending a request.

          So the key here is that the headers need to match the signature. For instance, your pre-signed URL has x-amz-acl=private So the upload must contain that header. Say my URL is:

          https://my-bucket-001.nyc3.digitaloceanspaces.com/hello.html?AWSAccessKeyId=EY3ALYH5DKS4EMBNQ5O3&Expires=1513180568&Signature=UeWfg%2Bb1XNBq6lHEjE7fZG4vZ%2Fc%3D&x-amz-acl=private
          

          Using curl for example purposes, my upload must look like:

          curl -X PUT -T "hello.html" \
            -H "x-amz-acl: private" \
            "https://my-bucket-001.nyc3.digitaloceanspaces.com/hello.html?AWSAccessKeyId=EY3ALYH5DKS4EMBNQ5O3&Expires=1513180568&Signature=UeWfg%2Bb1XNBq6lHEjE7fZG4vZ%2Fc%3D&x-amz-acl=private"
          

          Without including the header, I get the same error as you. With it, the upload succeeds. The same goes for things like content-type.

          • Isn't that silly that Digital Ocean doesn't support placing them as a get variable? It basically means I can't easily give this url to a third party and they blindly enter the url for upload. Now I have to make sure they set the headers too which adds more overhead of support. What was the logic behind this?

          • I definitely agree that it isn't ideal. Our initial focus with the Spaces API was to ensure that it was inter-operable with the S3 API so that users could continue using the same libraries and tools that they're already comfortable with. So we've inherited some warts there. This kind of feedback will help us as we start thinking about ways to make the Spaces API as intuitive as our others.

Create a Node.js app to upload a file to your DigitalOcean Space
  • Hey @johngannon thank you for the link but it looks like this guide does direct upload on express. For my needs I require using the signature URL. Can you direct me to a guide with v2 signatures?

Have another answer? Share your knowledge.