Closed asyschikov closed 10 months ago
Hi @asyschikov thanks for opening an issue. After looking into this issue I found that the problem could be because in this line the path is not being returned with a forward slash at the beginning, which may cause the signature mismatch. The documentation also state that even if the path is empty a forward slash should be returned. I will mark this issue to be reviewed so we can address this further, nonetheless a workaround you could use is to add the forward slash when you specify the path when constructing the request:
const request = { headers: { "Content-Type": "application/json", host: hostname, }, hostname, method: "POST", path: "/graphql", protocol: "https", body: JSON.stringify(body), };
, but you must remove the slash you add in between the host and the path when executing the request:
return axios.post(
${request.protocol}://${request.hostname}${request.path}
, body, { headers: signature.headers, } );
The complete code should look as follow:
import { URL } from "url";
import { SignatureV4 } from "@aws-sdk/signature-v4";
import pkg from "@aws-crypto/sha256-js";
const { Sha256 } = pkg;
import axios from "axios";
import { defaultProvider } from "@aws-sdk/credential-provider-node";
const credentialsProvider = defaultProvider();
const appSyncRequest = async (query, variables, graphQlUrl) => {
const url = new URL(graphQlUrl);
const hostname = url.hostname;
const body = {
query,
variables,
};
const request = {
headers: {
"Content-Type": "application/json",
host: hostname,
},
hostname,
method: "POST",
path: "/graphql",
protocol: "https",
body: JSON.stringify(body),
};
const signer = new SignatureV4({
credentials: credentialsProvider,
region: process.env.AWS_REGION ?? "eu-west-1",
service: "appsync",
sha256: Sha256,
});
const signature = await signer.sign(request);
console.log();
return axios.post(
`${request.protocol}://${request.hostname}${request.path}`,
body,
{
headers: signature.headers,
}
);
};
appSyncRequest(
`query { thisQueryDoesntHaveToExist }`,
{},
"https://REDACTED.appsync-api.eu-west-1.amazonaws.com/graphql"
)
.then((res) => {
console.log(JSON.stringify(res.data, null, 4));
})
.catch((error) => {
console.log(JSON.stringify(error, null, 4));
console.log(JSON.stringify(error.response.data, null, 4));
});
Thanks!
@yenfryherrerafeliz thanks for looking into it. The workaround is good too.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.
Describe the bug
I am using SignatureV4 to sign requests to AWS AppSync API (with IAM auth). It worked like magic until I recently upgraded to 3.58.0 (from 3.50.0). The error is "The request signature we calculated does not match the signature you provided" as if something broke in the algorithm. I have a minimal and sufficient code to replicate the issue but you will need an AppSync API for it (it can be empty, the goal is just to force IAM authentication).
Code:
Your environment
SDK version number
package.json
:Is the issue in the browser/Node.js/ReactNative?
Node.js
Details of the browser/Node.js/ReactNative version
Paste output of
npx envinfo --browsers
ornode -v
orreact-native -v
Steps to reproduce
Create a directory, save package.json and the code as test.js . Run npm i, provide AWS credentials, then node test.js . Then change
"@aws-sdk/signature-v4": "3.58.0" -> "@aws-sdk/signature-v4": "3.50.0",
run npm i and compare results.Observed behavior
Signature validates successfully on the AWS side.
Expected behavior
Signature DOESN'T validates successfully on the AWS side.
Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
I assume this has something to do with https://github.com/aws/aws-sdk-js-v3/issues/3408 because it was the only change inbetween.