aws-sdk-js: SignatureDoesNotMatch when using results of getSignedUrl

Hi,

we keep receiving SignaturDoesNotMatch errors when using urls generated by the getSignedUrl method.

We’re using aws-sdk@2.1.4, node v0.10.33 and our bucket is located in ‘eu-central-1’.

Our code (we condensed it down to calling headBucket):

    var s3_config = config.get('s3');
    var s3 = new aws.S3({
        signatureVersion: 'v4',
        region: 'eu-central-1',
        accessKeyId: 'XXX',
        secretAccessKey: 'XXX'
    });

    var params = { Bucket: 'XXX' };
    s3.getSignedUrl('headBucket', params, function(err, data) {
            consumeSignedUrl('GET', null, data, function(err, result) {
                console.log('result', err);
            });
        });
    });

function consumeSignedUrl(method, payload, signedUrl, finishedCb) {
    var parsed = url.parse(signedUrl);
    var body = '';
    var request = http.request({ hostname: parsed.hostname, path: parsed.path, method: method }, function(res) {
        res.on('data', function(chunk) { body += chunk; });
        res.on('end', function() {
            parseString(body, function(err, answer) {
                if (answer["Error"]) {
                    finishedCb(answer["Error"], body);
                } else {
                    finishedCb(null, body);
                }
            });
        });
    });
    if (payload) request.write(payload);
    request.end();
}

It produces this error output:

Code: [ ‘SignatureDoesNotMatch’ ], Message: [ ‘The request signature we calculated does not match the signature you provided. Check your key and signing method.’ ], AWSAccessKeyId: [ ‘XXXXX’ ], StringToSign: [ ‘AWS4-HMAC-SHA256\n20150106T145451Z\n20150106/eu-central-1/s3/aws4_request\nb78901e33b473d8ed9b288ed054c4300f60e9db065b5baba9deb9ce81e1407c1’ ], SignatureProvided: [ ‘09517b4d27b7cc3104e69a3a81251ec05bb459247f029031d8be8de51cc96c42’ ], StringToSignBytes: [ ‘41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 32 30 31 35 30 31 30 36 54 31 34 35 34 35 31 5a 0a 32 30 31 35 30 31 30 36 2f 65 75 2d 63 65 6e 74 72 61 6c 2d 31 2f 73 33 2f 61 77 73 34 5f 72 65 71 75 65 73 74 0a 62 37 38 39 30 31 65 33 33 62 34 37 33 64 38 65 64 39 62 32 38 38 65 64 30 35 34 63 34 33 30 30 66 36 30 65 39 64 62 30 36 35 62 35 62 61 62 61 39 64 65 62 39 63 65 38 31 65 31 34 30 37 63 31’ ], CanonicalRequest: [ ‘GET\n/\nX-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXX%2F20150106%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20150106T145451Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host\nhost:xxxx.s3.eu-central-1.amazonaws.com\n\nhost\nUNSIGNED-PAYLOAD’ ], CanonicalRequestBytes: [ ‘47 45 54 0a 2f 0a 58 2d 41 6d 7a 2d 41 6c 67 6f 72 69 74 68 6d 3d 41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 26 58 2d 41 6d 7a 2d 43 72 65 64 65 6e 74 69 61 6c 3d 41 4b 49 41 4a 35 57 45 56 49 33 49 46 4e 37 4a 4a 36 52 41 25 32 46 32 30 31 35 30 31 30 36 25 32 46 65 75 2d 63 65 6e 74 72 61 6c 2d 31 25 32 46 73 33 25 32 46 61 77 73 34 5f 72 65 71 75 65 73 74 26 58 2d 41 6d 7a 2d 44 61 74 65 3d 32 30 31 35 30 31 30 36 54 31 34 35 34 35 31 5a 26 58 2d 41 6d 7a 2d 45 78 70 69 72 65 73 3d 39 30 30 26 58 2d 41 6d 7a 2d 53 69 67 6e 65 64 48 65 61 64 65 72 73 3d 68 6f 73 74 0a 68 6f 73 74 3a 70 63 76 69 73 69 74 2d 67 72 61 76 61 74 61 72 73 2d 74 65 73 74 2e 73 33 2e 65 75 2d 63 65 6e 74 72 61 6c 2d 31 2e 61 6d 61 7a 6f 6e 61 77 73 2e 63 6f 6d 0a 0a 68 6f 73 74 0a 55 4e 53 49 47 4e 45 44 2d 50 41 59 4c 4f 41 44’ ], RequestId: [ ‘D3AB0C2FAE7C90AE’ ], HostId: [ ‘sSsCUPBSFjkqhJRxLHdyL+NF9y4ln6vq0vgZih5gS6HslMF9FjKMmqdhIauBl0AxAzWOTsavta4=’ ]

Are we doing anything wrong?

Thanks Ruediger

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 17 (8 by maintainers)

Commits related to this issue

Most upvoted comments

In case someone else is looking at this and is in a similar situation as me, I got a similar SignatureDoesNotMatchError when my s3 bucket’s CORS Configuration did not contain <AllowedHeader>*</AllowedHeader>

I ran into this when moving from one bucket to another, copying all the settings except for the CORS Configuration.

I’ve been setting ContentLength to force node not to use TransferEncoding: chunked as we’d otherwise get a ‘A header you provided implies functionality that is not implemented’ error.

The SDK doesn’t actually send a request in getSignedUrl(), so you should be omitting it there and only providing it in your http.request() call. The issue here is that you probably don’t want to sign the request with a specific ContentLength.

For what it’s worth, I’m not able to reproduce this when testing with a signed URL through curl. Here’s a little snippet to return a signed URL:

// test.js
var AWS = require('aws-sdk');
var s3 = new AWS.S3({params: {Bucket: process.env.BUCKET, Key: process.env.KEY}});
console.log(s3.getSignedUrl('putObject', {ACL: 'public-read'}));

And then I run it successfully with this shell snippet:

$ curl -X PUT -d "hello world" `AWS_REGION=eu-central-1 BUCKET=mybucket KEY=mykey node test.js`
$ curl http://mybucket.s3.amazonaws.com/mykey
hello world

Maybe this issue is specific to the headers Node.js is sending? Can you print the headers that are part of your http.request?

Without ContentLength is not working, because almost every client includes the ContentLength header on his own and then the StringToSign need to include content length value.

An example captured from a 403 error I just got.

<StringToSign>PUT

image/jpeg 1507804869 x-amz-security-token:FQoDYXdzEMP//////////wEaDAKgdFD/xRX7K3eU5SLuAekvCkM7nOHWAQ0U61f0qz16SB9BPjotNPQNJWV5BIzfWpi4lI62O9BTKhvrTrU+qmIekv3YeJBcthZDcvMcPEcPcLBLcQ5Kjj8EaCe9ItFzbrasRvCZgbltFXoV5IbL15oXXqeEzaoljSGmoVFarrSC7A2HvWZ65Ga1hTiyJ+jYyJMnmXHmW9d9vy6TVs/sl2acWoYPmNZiOtF0pw520C3pTKNfO57t1rQvsmoXHErfF2iVptVToW6EedlhGE19Nq7/bkOL6b50F7YllMI7q1h7GjLEJi7YFROuuNcqkbg0o3oIiNv/r7j9gGT+Yz8o85OhzQU= /ugimages/2017/08/31/433bf3b349aa6292352eb2906a6108e42927dac725bcb8336e4c25949de232a9/765199c38ed9a6937b2ae219cf12fbc5e37c1bfae0d3b64ac026590967f0be7a.jpg</StringToSign><SignatureProvided>