Skip to content

@aws-sdk/signature-v4: Can't sign API Gateway requests, SHA256 not provided - TypeError: hashConstructor is not a constructor #3590

@a-h

Description

@a-h

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);
  });

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue is a bug.p3This is a minor priority issuequeuedThis issues is on the AWS team's backlogworkaround-availableThis issue has a work around available.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions