Closed zirkelc closed 5 months ago
try your hand at a PR :)
which AWS service and operation did you encounter this with?
I have two people reporting this as issue when using Amazon Open Search and path contains a *
character. YOu will find more details here: https://github.com/zirkelc/aws-sigv4-fetch/issues/10
I myself could reproduce this issue with AWS API Gateway.
The fix PR was released. It's not enforced as the minimum version in SDK packages yet, but you can get it via the ^x.y.z
range that AWS SDKs use for @smithy/*
packages if you update your package lockfile.
Bug
If the path or query string of an URI contains a
*
character, the calculated signature on the client differs from the signature AWS calculates on the server. This results in HTTP 403 errors withThe request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method.
Investigation
The
SignatureV4
class andgetCanonicalPath
method encodes the path only with defaultencodeURIComponent
function:https://github.com/smithy-lang/smithy-typescript/blob/66f2b660e6b1dfc40699772a51778086495fd2cf/packages/signature-v4/src/SignatureV4.ts#L316-L336
However, the
getCanonicalQuery
function encodes the query string with theescapeUri
function:https://github.com/smithy-lang/smithy-typescript/blob/66f2b660e6b1dfc40699772a51778086495fd2cf/packages/signature-v4/src/getCanonicalQuery.ts#L9-L37
This
escapeUri
function encodes the URI according to RFC 3986:https://github.com/smithy-lang/smithy-typescript/blob/66f2b660e6b1dfc40699772a51778086495fd2cf/packages/util-uri-escape/src/escape-uri.ts#L4-L8
The requirement for RFC 3986 encoded URIs is also described in the official docs
https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html
The last important section refers to the
SdkHttpUtils.urlEncode
method from the Java SDK:https://github.com/aws/aws-sdk-java/blob/1b3444aa78f4579c4083bd4b3858322bc343a906/aws-java-sdk-core/src/main/java/com/amazonaws/util/SdkHttpUtils.java#L66-L99
In the Java code, the
*
will be encoded as%2A
. This encoding follow RFC3986 that specifies that the characters! ' ( ) *
must be encoded. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#encoding_for_rfc3986Here is also a PR from the Amplify project that implemented RFC 3986 encoding for the query string: https://github.com/aws-amplify/amplify-js/pull/2631
Conclusion
This issue can of course be mitigated if the requester encodes the URI on their own according to extendedURIEncode function. However, to be consistent with other AWS SDKs and fully compliant with the SignatureV4 spec, I think this part should be handled by the
SignatureV4
class and not by the requester.As there is also a
escapeUriPath
function, I would suggest adding toSignatureV4.getCanonicalPath
:https://github.com/smithy-lang/smithy-typescript/blob/66f2b660e6b1dfc40699772a51778086495fd2cf/packages/util-uri-escape/src/escape-uri-path.ts#L6C14-L6C27