S3RequestPresigner#presign causes SignatureDoesNotMatch error when S3 object key contains = #4862
-
Checkboxes for prior research
Describe the bugI tried to get presigned URL with custom parameter, so I implement below code. SDK version number@aws-sdk/client-s3: ^3.347.0 @aws-sdk/protocol-http: ^3.347.0 @aws-sdk/s3-request-presigner: ^3.347.0 @aws-sdk/util-format-url: ^3.347.0 Which JavaScript Runtime is this issue in?Node.js Details of the browser/Node.js/ReactNative versionnode v18.15.0, google chrome v113.0.5672.126 Reproduction Stepsimport { GetObjectCommand, S3Client } from "@aws-sdk/client-s3"
import { HttpRequest } from "@aws-sdk/protocol-http"
import { S3RequestPresigner, getSignedUrl } from "@aws-sdk/s3-request-presigner"
import { formatUrl } from "@aws-sdk/util-format-url"
async function getPresignedDownloadUrl(params: {
bucket: string
key: string
customParam: string
fileName?: string
downloadUrlExpirationSec?: number
}): Promise<string> {
const apiUrl = new URL(
`https://${params.bucket}.s3.amazonaws.com/${params.key}`
)
const presigner = new S3RequestPresigner({
...s3Client.config,
})
const httpRequest = new HttpRequest({
query: {
custom_param: params.customParam,
"response-content-disposition":
params.fileName != null
? `attachment; filename=${params.fileName}`
: "attachment",
},
hostname: apiUrl.hostname,
method: "GET",
path: apiUrl.pathname,
})
const signedRequest = await presigner.presign(httpRequest, {
expiresIn: params.downloadUrlExpirationSec ?? 60,
})
const downloadUrl = formatUrl(signedRequest)
return downloadUrl
}
const url = await getPresignedUrl({
bucket: "test_bucket",
customParam: "customParamValue",
key: "path/to/object", // Error occurs if "=" is included.
fileName: "name_of_download_file",
})
console.log(url) Enter above url in the brower's address bar. Observed BehaviorWhen entering presigned URL generated by above code in browser, SignatureDoesNotMatch occurs. Expected BehaviorNo SignatureDoesNotMatch occurs and can download properly. Possible SolutionNo response Additional Information/ContextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
Hi @sayyajp, sorry to hear about your issues. By reading the documentation about key naming guidelines, which can be found here, we can see that the symbol "=" is an special character and need special handling. Basically, in this case what you need to do is to URI-encode the key parameter. This is already handle by the getSignedUrl method, but since you are customizing your request then you need to do it yourself. Here is an example for how you can do it: const apiUrl = new URL(
`https://${params.bucket}.s3.amazonaws.com/${params.key}`
) You need to do: const apiUrl = new URL(
`https://${params.bucket}.s3.amazonaws.com/${encodeURIComponent(params.key)}`
); And that should fix your issue. I hope this helps! Thanks! |
Beta Was this translation helpful? Give feedback.
-
I am going to convert this into a discussion so that people facing similar issue can find guidance regarding. Thanks! |
Beta Was this translation helpful? Give feedback.
-
Hello! Reopening this discussion to make it searchable. |
Beta Was this translation helpful? Give feedback.
Hi @sayyajp, sorry to hear about your issues. By reading the documentation about key naming guidelines, which can be found here, we can see that the symbol "=" is an special character and need special handling. Basically, in this case what you need to do is to URI-encode the key parameter. This is already handle by the getSignedUrl method, but since you are customizing your request then you need to do it yourself. Here is an example for how you can do it:
Instead of:
You need to do:
And that sho…