aws-sigv4-sign
A small library for signing HTTP requests with AWS Signature Version 4 (SigV4) authentication, built with the official AWS SDK.
[!TIP]
If you are using the fetch
API, consider using the aws-sigv4-fetch
package to automatically sign requests.
Install
npm install --save aws-sigv4-sign
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 module format.
import { signRequest } from 'aws-sigv4-sign';
const { signRequest } = require('aws-sigv4-sign');
Usage
This package exports a signRequest
function that returns a Request
object with signed headers for AWS Signature V4 (SigV4) authentication.
The function is overloaded with the same signature as the fetch
API and an optional options
parameter.
import { signRequest, SignRequestOptions } from 'aws-sigv4-sign';
const options: SignRequestOptions = {
service: 'lambda',
region: 'eu-west-1',
credentials: {
accessKeyId: '...',
secretAccessKey: '...',
sessionToken: '...',
}
};
const url = 'https://mylambda.lambda-url.eu-west-1.on.aws/';
const signedRequest = await signRequest(url, options);
const signedRequest = await signRequest(new URL(url), options);
const signedRequest = await signRequest(new Request(url), options);
const signedRequest = await signRequest(url,
{
method: 'POST',
body: JSON.stringify({ a: 1 }),
headers: { 'Content-Type': 'application/json' }
},
options
);
The returned Request
object contains the signed authorization headers
with the following keys: authorization
, host
, x-amz-date
, x-amz-content-sha256
, x-amz-security-token
(optional).
const signedRequest = await signRequest(url, options);
const response = await fetch(signedRequest);
console.log(signedRequest.headers.get('authorization'));
console.log(signedRequest.headers.get('host'));
console.log(signedRequest.headers.get('x-amz-date'));
console.log(signedRequest.headers.get('x-amz-content-sha256'));
console.log(signedRequest.headers.get('x-amz-security-token'));
const headers = Object.fromEntries(signedRequest.headers.entries());
console.log(headers.authorization);
The headers
is a Headers
object and can be converted to plain object for use with other HTTP libraries.
Options
The signRequest
function accepts the following options:
service | string | Required | The service is required and must match the AWS service you are signing requests for. If it doesn't match, the request will fail with an error like: Credential should be scoped to correct service: 'service' . |
region | string | us-east-1 | The region is optional and defaults to us-east-1 if not provided. Some services like IAM are global and don't require a region. |
credentials | AwsCredentialIdentity | Optional in Node.js, required in browser | The credentials is optional in Node.js environments where they will be retrieved from the environment using @aws-sdk/credential-provider-node . In browser environments, credentials are required and must be provided explicitly. |
Credentials
The credentials
have type AwsCredentialIdentity
and consist of an accessKeyId
, secretAccessKey
and optionally a sessionToken
. Credential handling differs between Node.js and browser environments:
Node.js
In Node.js environments, credentials are optional. If not provided, they will be automatically loaded from the environment using @aws-sdk/credential-provider-node
, which checks several sources in this order:
- Environment variables exposed via process.env
- SSO credentials from token cache
- Web identity token credentials
- Shared credentials and config ini files
- The EC2/ECS Instance Metadata Service
Browser
In browser environments, credentials are required and must be provided explicitly for security reasons. The recommended method to provide credentials is to use Amazon Cognito Identity or web federated identity providers using @aws-sdk/credential-providers
.
[!WARNING]
Never hardcode AWS credentials in browser applications. Hard coding credentials poses a risk of exposing your access key ID and secret access key.
import { fromCognitoIdentity } from "@aws-sdk/credential-providers"
const signedRequest = await signRequest('https://mylambda.lambda-url.eu-west-1.on.aws/', {
service: 'lambda',
region: 'eu-west-1',
credentials: fromCognitoIdentity({
identityId: "us-east-1:128d0a74-c82f-4553-916d-90053example",
customRoleArn: "arn:aws:iam::1234567890:role/MYAPP-CognitoIdentity",
logins: {
"graph.facebook.com": "FBTOKEN",
"www.amazon.com": "AMAZONTOKEN",
"accounts.google.com": "GOOGLETOKEN",
"api.twitter.com": "TWITTERTOKEN'",
"www.digits.com": "DIGITSTOKEN",
},
clientConfig: {},
}),
});
Examples
The following examples show how to use the signed request with different HTTP libraries.
import { signRequest } from "aws-sigv4-sign";
const signedRequest = await signRequest('https://mylambda.lambda-url.eu-west-1.on.aws/', { service: 'lambda', region: 'eu-west-1' });
const response = await fetch(signedRequest);
import axios from "axios";
import { signRequest } from "aws-sigv4-sign";
const signedRequest = await signRequest('https://mylambda.lambda-url.eu-west-1.on.aws/', { service: 'lambda', region: 'eu-west-1' });
const headers = Object.fromEntries(signedRequest.headers.entries());
const response = await axios(signedRequest.url, { headers });
import { signRequest } from "aws-sigv4-sign";
import got from "got";
const signedRequest = await signRequest('https://mylambda.lambda-url.eu-west-1.on.aws/', { service: 'lambda', region: 'eu-west-1' });
const headers = Object.fromEntries(signedRequest.headers.entries());
const response = await got(signedRequest.url, { headers });
import { signRequest } from "aws-sigv4-sign";
import ky from "ky";
const signedRequest = await signRequest('https://mylambda.lambda-url.eu-west-1.on.aws/', { service: 'lambda', region: 'eu-west-1' });
const headers = Object.fromEntries(signedRequest.headers.entries());
const response = await ky.get(signedRequest.url, { headers });
import { signRequest } from "aws-sigv4-sign";
import { request } from "node:https";
const signedRequest = await signRequest('https://mylambda.lambda-url.eu-west-1.on.aws/', { service: 'lambda', region: 'eu-west-1' });
const headers = Object.fromEntries(signedRequest.headers.entries());
const body = "";
const response = new Promise((resolve, reject) => {
const req = request(signedRequest.url, { headers }, (res) => {
let data = "";
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () =>
resolve({
status: res.statusCode ?? 0,
statusText: res.statusMessage,
data,
}),
);
});
req.on("error", reject);
if (body) {
req.write(body);
}
req.end();
});
License
MIT