-
Notifications
You must be signed in to change notification settings - Fork 646
Description
Describe the bug
#460 deals with the issue for the Cognito Identity Provider, but the issue that the sha256 field is not set with a default implementation remains in the SDK when used for signing requests for API Gateway or other purposes.
Your environment
SDK version number
@aws-sdk/signature-v4@3.78.0
Is the issue in the browser/Node.js/ReactNative?
Node.js
Details of the browser/Node.js/ReactNative version
Node 16.x
Steps to reproduce
Please share code or minimal repo, and steps to reproduce the behavior.
const axios = require("axios");
const { SignatureV4 } = require("@aws-sdk/signature-v4");
const { HttpRequest } = require("@aws-sdk/protocol-http");
// const { Sha256 } = require("@aws-crypto/sha256-js");
const { defaultProvider } = require("@aws-sdk/credential-provider-node");
const signer = new SignatureV4({
credentials: defaultProvider(),
// sha256: Sha256,
region: "eu-west-1",
service: "execute-api",
});
async function post(apiUrl, data) {
const parsedUrl = new URL(apiUrl);
const endpoint = parsedUrl.hostname.toString();
const path = parsedUrl.pathname.toString();
const req = new HttpRequest({
hostname: endpoint,
path,
method: "POST",
body: JSON.stringify(data),
headers: {
host: endpoint,
"Content-Type": "application/json",
},
});
const signed = await signer.sign(req, { signingDate: new Date() });
return axios.post(apiUrl, signed.body, { headers: signed.headers });
}
send("https://xxxxx.execute-api.eu-west-1.amazonaws.com/prod/test", { data: "123" })
.then((res) => {
console.log("Success", res);
})
.catch((err) => {
console.log("Error", err);
});Observed behavior
Error: TypeError: hashConstructor is not a constructor
Expected behavior
Success, since there's a SHA256 implementation built into Node.js. However, that seems not to be compatible directly with this library, requiring a 3rd party to be used.
Workaround
After quite a bit of searching and looking through AWS examples and docs, adapting the example from https://stackoverflow.com/a/72001517 I was able to construct a working version, which uses the @aws-crypto/sha256-js library as an implementation.
const axios = require("axios");
const { SignatureV4 } = require("@aws-sdk/signature-v4");
const { HttpRequest } = require("@aws-sdk/protocol-http");
const { Sha256 } = require("@aws-crypto/sha256-js");
const { defaultProvider } = require("@aws-sdk/credential-provider-node");
const signer = new SignatureV4({
credentials: defaultProvider(),
sha256: Sha256,
region: "eu-west-1",
service: "execute-api",
});
async function post(apiUrl, data) {
const parsedUrl = new URL(apiUrl);
const endpoint = parsedUrl.hostname.toString();
const path = parsedUrl.pathname.toString();
const req = new HttpRequest({
hostname: endpoint,
path,
method: "POST",
body: JSON.stringify(data),
headers: {
host: endpoint,
"Content-Type": "application/json",
},
});
const signed = await signer.sign(req, { signingDate: new Date() });
return axios.post(apiUrl, signed.body, { headers: signed.headers });
}
send("https://xxxxx.execute-api.eu-west-1.amazonaws.com/prod/test", { data: "123" })
.then((res) => {
console.log("Success", res);
})
.catch((err) => {
console.log("Error", err);
});