Skip to content

Signer

This utility provides a way to sign HTTP requests to AWS services using the AWS Signature Version 4 (SigV4) signing process, so you can call IAM-authenticated endpoints such as Amazon API Gateway, AWS Lambda function URLs, or AWS AppSync from within your Lambda functions.

Key features

  • Sign web-standard Request objects with AWS Signature Version 4
  • Drop-in signed fetch for sending signed requests in one step
  • Works with any HTTP client by exposing the signed request and headers
  • Reads credentials and region from the Lambda runtime by default, with no extra dependencies

Getting started

1
npm install @aws-lambda-powertools/signer

The signer takes a web-standard Request (or anything you can pass to fetch, like a URL string) and returns a new, signed Request with the SigV4 headers added. It performs no network I/O, so you stay in control of how the request is sent.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import { SigV4Signer } from '@aws-lambda-powertools/signer/sigv4';

const signer = new SigV4Signer({ service: 'execute-api' });

export const handler = async () => {
  const signed = await signer.sign(
    'https://example.execute-api.us-east-1.amazonaws.com/items'
  );

  // `signed` is a standard `Request` with the SigV4 headers added
  const response = await fetch(signed);
  await response.json();
};

By default, the signer reads the AWS credentials and region from the environment variables that the Lambda runtime always provides, so no additional configuration is required when running in Lambda.

The service is required

The service name (for example execute-api, lambda, or appsync) cannot be reliably determined from the request URL, since custom domains and Amazon CloudFront hide the underlying service. You must always provide it.

Sending signed requests

If all you want is to sign and immediately send the request, use createSignedFetcher. It consumes a signer instance and returns a function with the same signature as the global fetch, signing each request before sending it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import { createSignedFetcher } from '@aws-lambda-powertools/signer/fetch';
import { SigV4Signer } from '@aws-lambda-powertools/signer/sigv4';

const signer = new SigV4Signer({ service: 'execute-api' });
const signedFetch = createSignedFetcher(signer);

export const handler = async () => {
  // `signedFetch` is a drop-in `fetch` that signs each request before sending it
  const response = await signedFetch(
    'https://example.execute-api.us-east-1.amazonaws.com/items',
    {
      method: 'POST',
      body: JSON.stringify({ name: 'powertools' }),
    }
  );

  await response.json();
};

Because the returned function is a drop-in fetch, you can also pass it to libraries that accept a custom fetch implementation.

Using other HTTP clients

Signing and sending are deliberately kept separate, so you can use the signed request with any HTTP client (for example axios, got, a generated SDK client, or a request interceptor). Call sign() to obtain a signed Request, then read its url, method, and headers.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import { SigV4Signer } from '@aws-lambda-powertools/signer/sigv4';

const signer = new SigV4Signer({ service: 'execute-api' });

export const handler = async () => {
  const signed = await signer.sign(
    'https://example.execute-api.us-east-1.amazonaws.com/items',
    { method: 'POST', body: JSON.stringify({ name: 'powertools' }) }
  );

  // Extract the signed headers to use them with any HTTP client, e.g. an
  // interceptor for axios, got, or a generated SDK client.
  const headers: Record<string, string> = {};
  for (const [key, value] of signed.headers) {
    headers[key] = value;
  }

  // `signed.url`, `signed.method`, and `headers` can now be passed to the
  // client of your choice.
};

Advanced

Configuring the region

The region defaults to the AWS_REGION environment variable that Lambda sets. You can override it, for example to sign requests for a service in a different region.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import { SigV4Signer } from '@aws-lambda-powertools/signer/sigv4';

const signer = new SigV4Signer({
  service: 'execute-api',
  region: 'eu-west-1', // (1)!
});

export const handler = async () => {
  const signed = await signer.sign(
    'https://example.execute-api.eu-west-1.amazonaws.com/items'
  );

  await fetch(signed);
};

export { signer };
  1. The region option takes precedence over the AWS_REGION environment variable.

Configuring credentials

When running outside of Lambda, the standard AWS credentials environment variables may not be set. In that case, pass your own credentials or a credential provider, such as fromNodeProviderChain() from @aws-sdk/credential-provider-node, which you install yourself.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import { SigV4Signer } from '@aws-lambda-powertools/signer/sigv4';

// By default, credentials are read from the standard AWS environment variables
// that the Lambda runtime injects. When running outside of Lambda, pass your
// own credentials or a credential provider, for example
// `fromNodeProviderChain()` from `@aws-sdk/credential-provider-node`.
const signer = new SigV4Signer({
  service: 'execute-api',
  credentials: {
    accessKeyId: process.env.MY_ACCESS_KEY_ID ?? '',
    secretAccessKey: process.env.MY_SECRET_ACCESS_KEY ?? '',
  },
});

export const handler = async () => {
  const signed = await signer.sign(
    'https://example.execute-api.us-east-1.amazonaws.com/items'
  );

  await fetch(signed);
};

Handling errors

The signer throws typed errors that all extend SignerError:

Error When it is thrown
SignerConfigError The region cannot be determined (at construction), or credentials are missing or cannot be resolved.
RequestSigningError Signing the request fails, for example because the request body cannot be read or replayed.
SignerError Base class for the errors above. Catch this to handle any signer error.

You can import them from the @aws-lambda-powertools/signer/errors subpath.

Request bodies

To compute the request signature, the request body is buffered and hashed. Strings, buffers, and finite streams are handled transparently. A body that cannot be read or replayed — for example a stream that errors mid-read — cannot be signed and raises a RequestSigningError.