A Simple Way to Sign AWS Requests with Signature V4

zirkelc

Chris Cook

Posted on March 27, 2024

A Simple Way to Sign AWS Requests with Signature V4

In a previous article, I explored the challenges of using Lambda Function URLs with IAM authorization and CloudFront custom domains. A key aspect of this setup involves signing HTTP requests with AWS Signature Version 4 (SigV4) to authenticate with IAM.

While the AWS SDK provides utilities for SigV4 signing, the process can be somewhat cumbersome, especially when working with the barebone functions like fetch instead of SDKs. To simplify this process, I've created the aws-sigv4-fetch package, which automatically signs fetch requests with SigV4 for a given AWS service and region.

What is AWS Signature Version 4?

AWS Signature Version 4 (SigV4) is a process for adding authentication information to AWS API requests sent over HTTP. For security reasons, most requests to AWS must be signed with an access key, which consists of an access key ID and a secret access key (your AWS credentials).

The SigV4 signing process involves creating a canonical request based on the HTTP request details, calculating a signature using your AWS credentials, and adding this signature to the request as an Authorization header. AWS then replicates this process and verifies the signature, granting or denying access accordingly.

For a more detailed explanation of SigV4, refer to my previous article or the AWS documentation.

Sign All Requests

The aws-sigv4-fetch package aims to simplify the SigV4 signing process for modern JavaScript applications. It exports a single function, createSignedFetcher, which returns a fetch function that automatically signs HTTP requests with SigV4 for the specified AWS service and region.

Here's an example usage:

import { createSignedFetcher } from 'aws-sigv4-fetch';

const signedFetch = createSignedFetcher({ service: 'execute-api', region: 'eu-west-1' });
const url = 'https://restapi.execute-api.eu-west-1.amazonaws.com/foo/bar';

const response = await signedFetch(url);

const data = await response.json();
Enter fullscreen mode Exit fullscreen mode

In this example, we create a signedFetch function that automatically signs requests to API Gateway in the eu-west-1 region. We can then use this function like a regular fetch, passing in the URL and request options. The aws-sigv4-fetch package will handle the SigV4 signing process behind the scenes, adding the necessary Authorization header to the request.

The createSignedFetcher function accepts an optional fetch argument, allowing you to pass in a custom fetch implementation (e.g., a polyfill like cross-fetch). If no fetch is provided, it defaults to the native fetch function which is available in Node.js since v18.

ESM and CommonJS Support

The aws-sigv4-fetch package is available on npm and can be installed with your preferred package manager:

npm install aws-sigv4-fetch
Enter fullscreen mode Exit fullscreen mode

The package supports both ES Modules and CommonJS, so you can import or require it as needed:

// ESM
import { createSignedFetcher } from 'aws-sigv4-fetch';

// CommonJS
const { createSignedFetcher } = require('aws-sigv4-fetch');

const signedFetch = createSignedFetcher({ service: 'appsync', region: 'eu-west-1' });
Enter fullscreen mode Exit fullscreen mode

Integration with GraphQL Libraries

The aws-sigv4-fetch package can be integrated into GraphQL libraries like graphql-request. For example, you can pass the signedFetch function as the custom fetch option:

import { createSignedFetcher } from 'aws-sigv4-fetch';
import { GraphQLClient } from 'graphql-request';

const signedFetch = createSignedFetcher({ service: 'appsync', region: 'eu-west-1' });

const client = new GraphQLClient('https://graphqlapi.appsync-api.eu-west-1.amazonaws.com/graphql', {
  fetch: signedFetch,
});

const result = await client.request(query, variables);
Enter fullscreen mode Exit fullscreen mode

With this setup, all GraphQL requests made through the client will be automatically signed with SigV4.

Contributions

I am in the process of adding E2E tests for AWS services. So far only API Gateway and IAM are covered by tests with real resources. If you are using a specific AWS service and want to make sure that aws-sigv4-fetch always works with that service, I would greatly appreciate your contribution. Of course, feedback and improvements are always welcome.

GitHub logo zirkelc / aws-sigv4-fetch

AWS SignatureV4 fetch function built on the official AWS SDK for JS

CI npm npm

aws-sigv4-fetch

AWS SignatureV4 fetch API function to automatically sign HTTP request with given AWS credentials. Built entirely on the newest version of the official AWS SDK for JS.

Signature Version 4

Signature Version 4 (SigV4) is the process to add authentication information to AWS API requests sent by HTTP. For security, most requests to AWS must be signed with an access key. The access key consists of an access key ID and secret access key, which are commonly referred to as your security credentials

AWS documentation on Signature Version 4 signing process

Install

npm install --save aws-sigv4-fetch

yarn add aws-sigv4-fetch

pnpm add aws-sigv4-fetch
Enter fullscreen mode Exit fullscreen mode

ESM and CommonJS

This package ships with ES Module and CommonJS support. That means you can import or require the package in your project depending on your mdoule format.

// ESM
import { createSignedFetcher } from 'aws-sigv4-fetch';
// CommonJS
const { createSignedFetcher } = require
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
zirkelc
Chris Cook

Posted on March 27, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related