Skip to content

Commit 1eaeb85

Browse files
Allow authorization using queryString when using wss-custom-auth. (#383)
Co-authored-by: Stijn De Pestel <[email protected]>
1 parent fda92f8 commit 1eaeb85

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ follows:
368368
* `customAuthHeaders`: used to specify your custom authorization headers when `protocol` is set to 'wss-custom-auth'. The fields 'X-Amz-CustomAuthorizer-Name', 'X-Amz-CustomAuthorizer-Signature', and the field for your token name are required.
369369
* `servername`: used for SNI. If undefined, a value is derived from `host`.
370370
* `port`: used to specify which port to connect to. If undefined, 443 or 8883 will be chosen depending on `protocol`.
371+
* `customAuthQueryString`: used to specify the token credentials in a query string for custom authorization when `protocol` is set to `wss-custom-auth`. More info can be found [here](https://docs.aws.amazon.com/iot/latest/developerguide/custom-auth.html#custom-auth-websockets).
371372
* `keepalive`: used to specify the time interval for each ping request. Default is set to 300 seconds to connect to AWS IoT.
372373
* `enableMetrics`: used to report SDK version usage metrics. It is set to true by default. To disable metrics collection, set value to false.
373374
* `debug`: set to 'true' for verbose logging (default 'false').
@@ -746,8 +747,8 @@ set the `protocol` option to `wss-custom-auth`.
746747
### Custom Authorization Configuration
747748

748749
To use custom authorization, you must first set up an authorizer function in Lambda and register it
749-
with IoT. Once you do, you will be able to authenticate using this function. To use custom auth,
750-
set the `customAuthHeaders` option to your headers object when instantiating the [awsIotDevice()](#device)
750+
with IoT. Once you do, you will be able to authenticate using this function. There are two ways to use custom auth:
751+
* set the `customAuthHeaders` option to your headers object when instantiating the [awsIotDevice()](#device)
751752
or [awsIot.thingShadow()](#thingShadow) classes. The headers object is an object containing the header name
752753
and values as key-value pairs:
753754

@@ -758,6 +759,11 @@ and values as key-value pairs:
758759
'TestAuthorizerToken': 'token'
759760
}
760761
```
762+
* set the `customAuthQueryString` option to your headers object when instantiating the [awsIotDevice()](#device) class. The query string is a string containing the values as key-value pairs:
763+
764+
```js
765+
'?X-Amz-CustomAuthorizer-Name=TestAuthorizer&X-Amz-CustomAuthorizer-Signature=signature&TestAuthorizerToken=token'
766+
```
761767

762768

763769
<a name="programs"></a>

device/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ function prepareWebSocketCustomAuthUrl(options) {
172172
hostName = options.host + ':' + options.port;
173173
}
174174

175-
return 'wss://' + hostName + path;
175+
return 'wss://' + hostName + path + (options.customAuthQueryString || '');
176176
}
177177

178178
function arrayEach(array, iterFunction) {
@@ -505,8 +505,8 @@ function DeviceClient(options) {
505505
throw new Error(exceptions.INVALID_CONNECT_OPTIONS);
506506
}
507507
} else {
508-
if (isUndefined(options.customAuthHeaders)) {
509-
console.log('To authenticate with a custom authorizer, you must provide the required HTTP headers; see README.md');
508+
if (isUndefined(options.customAuthHeaders) && isUndefined(options.customAuthQueryString)) {
509+
console.log('To authenticate with a custom authorizer, you must provide the required HTTP headers or queryString; see README.md');
510510
throw new Error(exceptions.INVALID_CONNECT_OPTIONS);
511511
}
512512
}

test/device-unit-tests.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ describe( "device class unit tests", function() {
546546
);
547547
});
548548
});
549-
describe("device throws exception if using CustomAuth over websocket without headers", function () {
549+
describe("device throws exception if using CustomAuth over websocket without headers or querystring", function () {
550550
it("throws exception", function () {
551551
assert.throws(function (err) {
552552
var device = deviceModule({
@@ -557,6 +557,30 @@ describe( "device class unit tests", function() {
557557
);
558558
});
559559
});
560+
describe("device does not throw exception if using CustomAuth over websocket with headers", function () {
561+
it("does not throw an exception", function () {
562+
assert.doesNotThrow(function (err) {
563+
var device = deviceModule({
564+
host: 'XXXX.iot.us-east-1.amazonaws.com',
565+
protocol: 'wss-custom-auth',
566+
customAuthHeaders: {}
567+
});
568+
}, function (err) { console.log('\t[' + err + ']'); return true; }
569+
);
570+
});
571+
});
572+
describe("device does not throw exception if using CustomAuth over websocket with querystring", function () {
573+
it("does not throw an exception", function () {
574+
assert.doesNotThrow(function (err) {
575+
var device = deviceModule({
576+
host: 'XXXX.iot.us-east-1.amazonaws.com',
577+
protocol: 'wss-custom-auth',
578+
customAuthQueryString: ''
579+
});
580+
}, function (err) { console.log('\t[' + err + ']'); return true; }
581+
);
582+
});
583+
});
560584
describe("device does not throw exception if using CustomAuth over websocket with non-standard headers", function () {
561585
it("does not throw an exception", function () {
562586
assert.doesNotThrow(function (err) {
@@ -1888,6 +1912,15 @@ describe( "device class unit tests", function() {
18881912
assert.equal( url, expectedUrl );
18891913
});
18901914
});
1915+
describe("websocket http querystring is correctly set when CustomAuth querystring is specified", function() {
1916+
it("generates the correct url", function() {
1917+
const queryString = '?X-Amz-CustomAuthorizer-Name=AuthorizerFunctionName&X-Amz-CustomAuthorizer-Signature=Signature&NPAuthorizerToken=Token';
1918+
const expectedUrl = 'wss://not-a-real-host.com/mqtt' + queryString;
1919+
const url = deviceModule.prepareWebSocketCustomAuthUrl( { host:'not-a-real-host.com', customAuthQueryString: queryString } );
1920+
assert.equal( url, expectedUrl );
1921+
});
1922+
1923+
});
18911924
describe("websocket headers are correctly set when CustomAuth headers are specified", function() {
18921925
it("sets the websocket headers correctly", function() {
18931926
var headers = {

0 commit comments

Comments
 (0)