aws-sdk-js: getSignedUrl not always returning a valid signed-url
Confirm by changing [ ] to [x] below to ensure that it’s a bug:
- I’ve gone through Developer Guide and API reference
- I’ve checked AWS Forums and StackOverflow for answers
- I’ve searched for previous similar issues and didn’t find any solution
Describe the bug
Sometimes when calling s3.getSignedUrl(method, params)
we receive an invalid signed URL from the SDK and no error is thrown. EG:https://s3.us-west-2.amazonaws.com/
This happens on both getObject and putObject methods, and retrying the call produces the expected results.
Is the issue in the browser/Node.js? Node.js
If on Node.js, are you running this on AWS Lambda? No Details of the browser/Node.js version Node v10.21.0
SDK version number v2.694.0
To Reproduce (observed behavior) Excerpt from our code
const AWS = require('aws-sdk');
const path = require('path');
const log = require('../logger');
const config = require('config');
const bucket = config.s3.uploads.bucket;
const region = config.s3.uploads.region;
const s3 = new AWS.S3({
apiVersion: '2006-03-01',
signatureVersion: 'v4',
region
});
async function getSignedUrl(method, params) {
try {
const preSignedUrl = s3.getSignedUrl(method, params);
if (!preSignedUrl.includes("X-Amz-Signature")) {
log.error(`received a non valid ${method} presigned url : ${preSignedUrl}`);
throw new Error ("Illegal presigned url returned!");
}
return preSignedUrl;
} catch (err) {
log.error(err, `Error retrieving ${method} pre-signed url`);
throw err;
}
}
Params being:
const uploadlinkparams = {
Key: prefix,
Bucket: bucket,
Expires: 60 * 60, // one hour
Tagging: "" // This header needs to exist otherwise we can't add tags
};
const downloadlinkparams = {
Key: prefix,
Bucket: bucket,
Expires: downloadttl ? downloadttl * 60 : 60 * 60 * 24 * 7 // 7 days if not specified
};
Expected behavior We expect to receive a valid pre-signed url, or an error to be thrown by the SDK
Screenshots N/A
Additional context This code runs on EC2 instances. I cannot reproduce locally outside of AWS. It is hard to reproduce in AWS.
We see the following calls made before the failure: PUT //169.254.169.254/latest/api/token [200] GET //169.254.169.254/latest/meta-data/iam/security-credentials/ [200] GET //169.254.169.254/latest/meta-data/iam/security-credentials/<censored>InstanceProfile [200]
With the failure message being: received a non valid putObject presigned url : https://s3.us-west-2.amazonaws.com/
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 5
- Comments: 19 (5 by maintainers)
Commenting to keep this open
As of today, it seems like a call to this function (promise or not) returns the bare legacy
https://s3.amazonaws.com/
while onlyhttps://s3.[region].amazonaws.com/
is allowed.Having the same problem here, tried changing to
await getSignedUrlPromise
without luckYep switched to
getSignedUrlPromise
seems good so far.I think there should be some documentation at-least about this failure-mode.
I ran into this issue. I solved it by adding
signatureVersion
to the AWS SDK config (see below). Without itgetSignedUrlPromise
will return a url without the signature field query string parameter. This causes the URL not to work.when we get the image or video file from the aws getSignedUrl why the getting files are showing in the source page folder while doing the inspect element? How to avoid or clear the image files. Please anyone can explain immediately.
@Mnkras That can be regarded as a feature request but I think it has already been raised but since there is a workaround for that the priority for that is really low.
Also it will be beneficial for your app to use
getSignedUrlPromise
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrlPromise-property
It doesn’t solve your problem but I thought it can save you some lines of code.
@sshadmand I had the same issue, but I resolved it by adding an explicitly signature version like this: