From 96dc0c46ac32aecb88f3d849bd3e381d7d5b87a0 Mon Sep 17 00:00:00 2001 From: Vikhyat Korrapati Date: Wed, 11 Oct 2017 11:33:27 -0700 Subject: [PATCH] Improve AWS SigV4 support. This makes the following changes to the AWS SigV4 signing functionality: 1. Sign all request headers instead of just Content-Type. 2. Allow specifying a service name. --- README.md | 2 +- request.js | 7 ++++--- tests/test-aws.js | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cedc19d51..63a558271 100644 --- a/README.md +++ b/README.md @@ -772,7 +772,7 @@ The first argument can be either a `url` or an `options` object. The only requir - `auth` - a hash containing values `user` || `username`, `pass` || `password`, and `sendImmediately` (optional). See documentation above. - `oauth` - options for OAuth HMAC-SHA1 signing. See documentation above. - `hawk` - options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example). -- `aws` - `object` containing AWS signing information. Should have the properties `key`, `secret`, and optionally `session` (note that this only works for services that require session as part of the canonical string). Also requires the property `bucket`, unless you’re specifying your `bucket` as part of the path, or the request doesn’t use a bucket (i.e. GET Services). If you want to use AWS sign version 4 use the parameter `sign_version` with value `4` otherwise the default is version 2. **Note:** you need to `npm install aws4` first. +- `aws` - `object` containing AWS signing information. Should have the properties `key`, `secret`, and optionally `session` (note that this only works for services that require session as part of the canonical string). Also requires the property `bucket`, unless you’re specifying your `bucket` as part of the path, or the request doesn’t use a bucket (i.e. GET Services). If you want to use AWS sign version 4 use the parameter `sign_version` with value `4` otherwise the default is version 2. If you are using SigV4, you can also include a `service` property that specifies the service name. **Note:** you need to `npm install aws4` first. - `httpSignature` - options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options. --- diff --git a/request.js b/request.js index ff19ca39c..6fd89408e 100644 --- a/request.js +++ b/request.js @@ -1364,11 +1364,12 @@ Request.prototype.aws = function (opts, now) { host: self.uri.host, path: self.uri.path, method: self.method, - headers: { - 'content-type': self.getHeader('content-type') || '' - }, + headers: self.headers, body: self.body } + if (opts.service) { + options.service = opts.service + } var signRes = aws4.sign(options, { accessKeyId: opts.key, secretAccessKey: opts.secret, diff --git a/tests/test-aws.js b/tests/test-aws.js index 214003974..44f4f0b04 100644 --- a/tests/test-aws.js +++ b/tests/test-aws.js @@ -77,6 +77,45 @@ tape('aws-sign4 options with session token', function (t) { }) }) +tape('aws-sign4 options with service', function (t) { + var serviceName = 'UNIQUE_SERVICE_NAME' + var options = { + url: s.url + path, + aws: { + key: 'my_key', + secret: 'my_secret', + sign_version: 4, + service: serviceName + }, + json: true + } + request(options, function (err, res, body) { + t.error(err) + t.ok(body.authorization.includes(serviceName)) + t.end() + }) +}) + +tape('aws-sign4 with additional headers', function (t) { + var options = { + url: s.url + path, + headers: { + 'X-Custom-Header': 'custom' + }, + aws: { + key: 'my_key', + secret: 'my_secret', + sign_version: 4 + }, + json: true + } + request(options, function (err, res, body) { + t.error(err) + t.ok(body.authorization.includes('x-custom-header')) + t.end() + }) +}) + tape('cleanup', function (t) { s.close(function () { t.end()