aws-sdk-js: pre-signed S3 putObject URLs don't allow tags

I’m currently using the latest version of the aws-sdk-js. I have found what I think is a bug relating to uploading objects to an S3 bucket using the pre-signed URLs. If I create an object using the SDK like so:

const params = { Bucket, Key: 'testfile', Metadata, Body: "This is a test object", Tagging: 'sem=somethingSemantic' };
s3.putObject(params, (err, data) => {
  if (err) {
    console.log('s3 error: ', err);
  }
  console.log('it worked: ', data);
}

This works, I see an object called testfile appear in my bucket and it has a tag sem: somethingSemantic.

However, when I try to generate a url using the following code:

s3.getSignedUrl('putObject', { Bucket, Key: 'testfile', Metadata, Tagging: 'sem=somethingSemantic' Expires: 1800 }, (error, url) => {
  if (error) {
    console.log('s3 error: ', error);
  }
  console.log('The URL is', url);
}

This code generates a URL similar to the following: https://bucketname.s3.amazonaws.com/testfile?AWSAccessKeyId=mykey&Expires=1484777697&Signature=signatureString&x-amz-tagging=sem%3DsomethingSemantic When I do a put on this URL using postman and upload the binary file, it creates the file correctly, however it does NOT create the tag. Even more curious is the fact that if I take out the x-amz-tagging part of the pre-signed URL and manually input the header into postman, like so: image Everything works fine. Can someone verify if this is actually a bug or if something else is going on here? UPDATE: I ran the pre-signed URL in curl as well to verify this is not a postman issue, same behavior with curl, no tagging via pre-signed URLs.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 13
  • Comments: 22 (6 by maintainers)

Most upvoted comments

You also need to include the ‘x-amz-tagging’ header as a part of the actual PUT/POST request. Hope this helps!

There is something weird going on. It seems that when signing the url you must set just some random tag with it but you actually set real tags within the PUT operation.

Here’s my signing code:

    var signedURL = s3.getSignedUrl("putObject", {
        Bucket: "mybucket",
        Key: "foobar.pdf",
        ContentType: "application/pdf",
        ACL: "public-read",
        Tagging: "foo=anything",
    });

And here’s browser upload code

    const headers = new Headers();
    headers.append("x-amz-tagging", "myrealtag=tagvalue");

    const res = await fetch(signedURL, {
        method: "PUT",
        body: file,
        headers,
    });

Hey @epeli, re:

There is something weird going on. It seems that when signing the url you must set just some random tag with it but you actually set real tags within the PUT operation.

Here’s my signing code:

    var signedURL = s3.getSignedUrl("putObject", {
        Bucket: "mybucket",
        Key: "foobar.pdf",
        ContentType: "application/pdf",
        ACL: "public-read",
        Tagging: "foo=anything",
    });

And here’s browser upload code

    const headers = new Headers();
    headers.append("x-amz-tagging", "myrealtag=tagvalue");

    const res = await fetch(signedURL, {
        method: "PUT",
        body: file,
        headers,
    });

I had the exact same issue and was banging my head against a brick wall, but then I realized the current documentation notes that some params are not processed, including Tagging: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property. They need to be passed as headers, e.g. x-amz-tagging=mytagkey%3Dmytagvalue.

Regardless, I don’t see why this issue dies in December last year without someone from AWS mentioning this fact?

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. If you are using pre-signed URLs to upload from a browser and need to use these fields, see createPresignedPost().