aws / aws-sdk-js

AWS SDK for JavaScript in the browser and Node.js
https://aws.amazon.com/developer/language/javascript/
Apache License 2.0
7.6k stars 1.55k forks source link

S3 SignatureDoesNotMatch error when visiting presigned getObject URL in browser #3319

Closed harrisonturton closed 4 years ago

harrisonturton commented 4 years ago

Confirm by changing [ ] to [x] below:

Describe the question

Hello!

I am trying to allow my clients to download a file directly from S3. To do this, I generate a presigned URL and they render it as an <a href={presignedUrl}>...</a> in the browser. I am using React, if that matters.

This is how I initialise the s3 object:

const s3 = new AWS.S3({
    region: "ap-southeast-2",
    apiVersion: "2006-03-01",
    signatureVersion: "v4",
    signatureCache: false,
    accessKeyId: "access-key-id",
    secretAccessKey: "secret-access-key",
});

If it matters, the secretAccessKey has a / in it. I think I've seen that mentioned in other issues/stackoverflow.

And this is how I use it:

export const getSignedUrl = async (path: string): Promise<string> => {
    const url = await s3.getSignedUrlPromise("getObject", {
        Bucket: "my-bucket",
        Key: path,
        Expires: 60 * 60, // 1 hour
    });
    return url;
};

I get no errors when generating the URL, but when I visit the link in the browser, I get the following response:

SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your key and signing method.<data>GET <s3 object key> X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<access key><other stuff>aws4_request&X-Amz-Date=20200620T044918Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host host:<my s3 endpoint> host UNSIGNED-PAYLOAD<bunch of data here>

I've removed some of the data in case its sensitive.

This error response is close to the "Signature Does Not Match" section of the Troubleshooting section in the docs.

Potentially this is caused by the browsers generated request being different from what AWS expects –– e.g. perhaps it is missing, or has incorrect set, important headers.

Any advice on how to fix this? It's been doing my head in.

ajredniwja commented 4 years ago

Hey @harrisonturton thank-you for reaching out to us with your issue, the code you mentioned looks fine and should not be the issue. Can you try:

As simple as:

var params = {
    region: "us-west-2",
    apiVersion: "2006-03-01",
    signatureVersion: "v4",
    signatureCache: false,
}

var s3 = new AWS.S3(params);

const url = s3.getSignedUrl("getObject", {
    Bucket: "a",
    Key: 'a',
    Expires: 60 * 60, // 1 hour
});

console.log(url);
github-actions[bot] commented 4 years ago

This issue has not received a response in 1 week. If you still think there is a problem, please leave a comment to avoid the issue from automatically closing.

thefallenmerc commented 3 years ago

using the said config gives access denied error response, when using the signedUrl

aryang23 commented 5 months ago

Getting the same issue even when using the same config. First getting error, Key doesn't exists Tried uploading manually and then searching via URL Getting S3 SignatureDoesNotMatch.

aBurmeseDev commented 5 months ago

@aryang23 - sorry to hear you're running into this. Can you create a new issue with repro steps to your workflow? I'd be happy to look into it.