1

I try to upload jpeg image to the s3 bucket, I get Pre-sign URL successfully without any error but I always get the errors when I try to upload an image using that URL. Errors:

 <Code>AuthorizationQueryParametersError</Code>
    <Message>
    Error parsing the X-Amz-Credential parameter; the region 'us-east-1' is wrong; expecting 'eu-west-1'
    </Message>

I will explain steps how I did that:

1.Get presign url:

const s3 = new AWS.S3();
s3.config.update({
  accessKeyId: keys.accessKeyId,
  secretAcccessKey: keys.secretAcccessKey,
  signatureVersion: 'v4',
});
router.get('/', (req, res) => {
    const key = '123.jpeg';
    s3.getSignedUrl(
      'putObject', {
        Bucket: 'My bucket',
        ContentType: 'image/jpeg',
        Key: key,
        Expires: 1000
      },
      (e, url) => {
        if (e) {
          res.status(400).json(errors);
        } else {
          res.json({ url, key });
        }
      })
  });

After I get my Presighn URL I try to upload my image:

const options = {
        headers: {
          'Content-Type': File[0].type
        }
      };
      axios.put(uploadURL, File[0], options);

My bucket policy on amazon s3:

{
    "Version": "2012-10-17",
    "Id": "Policy17794",
    "Statement": [
        {
            "Sid": "damy",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::backetName/*",
            "Condition": {
                "NumericGreaterThan": {
                    "s3:signatureAge": "600000"
                }
            }
        }
    ]
}

Bucket Cors Configuration:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

Update: When I try to put the region:'eu-west-1' it give me another error said:

<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>

Update V2: I know where is the problem but I don't know why that happened, When I use pre_sign URL without login by passport everything going correct but when I log in using passport JWT I get SignatureDoesNotMatch error.

MohammadTofi
  • 365
  • 1
  • 7
  • 22
  • Looks like your expire time on the presigned url is set to 1000 milliseconds. Can you increase the expire time and try to upload and see if that works. – Rajesh Aug 13 '18 at 16:18
  • Thanks for the reply, I increase the expire time to 80000 and I get the same error. – MohammadTofi Aug 13 '18 at 16:40
  • I am assuming that your bucket is in the eu-west1 region. in the S3 Config object can you use eu-west1 region endpoint as well and try. Also your bucket policy has a condition on the S3SignatureAge to be greater than 600000. Should it be LessThan – Rajesh Aug 13 '18 at 16:45
  • I think the problem because I use a passport, somehow passport affects to pre-sign URL. – MohammadTofi Aug 14 '18 at 13:15

1 Answers1

1

I faced the same issue. It seems to be a very popular issue of AWS sdk version 1. I believe your s3 bucket has been assigned the region 'eu-west-1'.

It happens to be that 'eu-west-1' requires AWS version 4 signature and when you evaluate the signature from the signed Url, the region set while making the call, becomes the part of the signature string.

Here's the tricky part, when you directly make the call using endpoint 's3.amazonaws.com', the sdk does not know the reason to be used, and thus user any random region. In your case 'us-east-1', which does not match you bucket region and thus violates the version 4 signature.

The solution that I used, was to simply mention the region in s3 options, and may or may not mention signture version. Since anyways, the SDK would automatically set the signature version optimal for the region.

    let s3 = new AWS.S3({region: 'us-east-1'});