Sign requests to AWS with their Version 4 Signature algorithm.
Instead of importing the enormously huge aws-sdk (currently 46.4MB unpacked) you could use this as the basis for some much lighter tooling.
AWS provides a full test suite for the Version 4 Signature, and this library passes all tests except the invalid ones noted here.
The normal way:
npm install --save sign-aws-requests
Then require or import:
const { createAwsSigner } = require('sign-aws-requests')
// or
import { createAwsSigner } from 'sign-aws-requests'
This library exports a NodeJS and browser compatible version, your bundler should handle picking which one, but you can select manually:
- Browser, ES import/export -
dist/sign-aws-requests-browser.js
- Browser, CommonJS -
dist/sign-aws-requests-browser.cjs
- NodeJS, ES import/export -
dist/sign-aws-requests.js
- NodeJS, CommonJS -
dist/sign-aws-requests.cjs
Create a signer:
import { createAwsSigner } from 'sign-aws-requests'
const sign = createAwsSigner({
config: {
service: 'dynamodb',
region: 'us-east-1',
accessKeyId: 'AKIDEXAMPLE',
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY',
}
});
Create a request:
const request = {
url: 'https://dynamodb.us-east-1.amazonaws.com',
method: 'POST',
headers: {
'content-type': 'application/x-amz-json-1.0',
'X-Amz-Target': 'DynamoDB_20120810.GetItem',
'Host': 'dynamodb.us-east-1.amazonaws.com'
},
body: {
TableName: 'demo-sign-aws-requests',
Key: {
DemoPrimaryKey: {
S: 'DEMO'
},
DemoSortKey: {
S: '123'
}
}
}
};
Sign that request, generating the Authorization
header, which you then add to the request headers:
const { authorization, bodyString } = await sign(request)
request.headers.Authorization = authorization
request.body = bodyString
Note: if you pass in
body
as a string, you won't be able to use the Form URL Encoding described below, but everything else will work fine.
Some AWS endpoints (for example the SQS API) require the body of the request to be form URL encoded.
If you pass in body
as an object and set the option formencode
to true
, the bodyString
output will be correctly encoded.
For example:
const request = {
url: 'https://sqs.us-east-1.amazonaws.com',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Host': 'sqs.us-east-1.amazonaws.com',
},
body: {
Action: 'SendMessage',
MessageBody: '{"hello":"world"}',
}
}
const { authorization, bodyString } = await sign(request, { formencode: true })
request.headers.Authorization = authorization
request.body = bodyString
console.log(bodyString) // => 'Action=SendMessage&MessageBody=%7B%22hello%22%3A%22world%22%7D&Version=2012-11-05'
Note: Be sure to set the
Content-Type
header toapplication/x-www-form-urlencoded
or AWS might not like your request!
The initialize function returns a new instance configured to sign requests to a particular service. It takes an object with the following required options:
config: Object
- The AWS specific configuration properties.config.service: String
- The name of the AWS service, e.g.dynamodb
.config.region: String
- The AWS region, e.g.us-east-1
.config.accessKeyId: String
- The IAM access key id.config.secretAccessKey: String
- The IAM access key secret.
The returned property is the function used to sign requests.
The signing function takes an HTTP request object with the following required properties:
url: String
- The fully qualified URI, e.g. protocol, domain, path, and all query parameters.method: String
- The HTTP method.headers: Object
- The request headers. Note that this is a normal key to string value map, but if there are multiple values for the same header key, the value must be an array of strings.body: String
[optional] - The string value of the body.
The options object takes the following options properties:
formencode: Boolean
- Whether to convert thebody
to the Form URL Encoded version. (Default:false
)
The output of the signing function is an object containing the following properties:
authorization: String
- The value which you would place in the header.bodyString: String
- The original string or undefined, if those were passed in asbody
, or the stringified body. In the case of Form URL Encoded, it will be the encoded object string, and in other cases it will simply be passed throughJSON.stringify
.
The test files originated from AWS, but were given with an Apache 2.0 license.
This test suite, all other generated code, documentation, and assets, are released under the Very Open License