Last active
May 23, 2023 21:21
-
-
Save RyanSept/d9f98a333c1a45d680e2d114c908e184 to your computer and use it in GitHub Desktop.
Javascript AWS IoT MQTT WebSocket Client with AWS SigV4 Request Signing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// attribution: https://github.com/dwyl/learn-aws-iot/blob/46538441c4f6591eb23a7396d0a816ce8ff7806f/src/js/utils/request.js | |
var moment = require("moment"); | |
var CryptoJS = require("crypto-js"); | |
function SigV4Utils() {} | |
SigV4Utils.sign = function (key, msg) { | |
var hash = CryptoJS.HmacSHA256(msg, key); | |
return hash.toString(CryptoJS.enc.Hex); | |
}; | |
SigV4Utils.sha256 = function (msg) { | |
var hash = CryptoJS.SHA256(msg); | |
return hash.toString(CryptoJS.enc.Hex); | |
}; | |
SigV4Utils.getSignatureKey = function ( | |
key, | |
dateStamp, | |
regionName, | |
serviceName | |
) { | |
var kDate = CryptoJS.HmacSHA256(dateStamp, "AWS4" + key); | |
var kRegion = CryptoJS.HmacSHA256(regionName, kDate); | |
var kService = CryptoJS.HmacSHA256(serviceName, kRegion); | |
var kSigning = CryptoJS.HmacSHA256("aws4_request", kService); | |
return kSigning; | |
}; | |
function formatRequestUrl(options) { | |
var time = moment.utc(); | |
var dateStamp = time.format("YYYYMMDD"); | |
var amzdate = dateStamp + "T" + time.format("HHmmss") + "Z"; | |
var service = "iotdevicegateway"; | |
var region = options.regionName; | |
var secretKey = options.secretKey; | |
var accessKey = options.accessKey; | |
var algorithm = "AWS4-HMAC-SHA256"; | |
var method = "GET"; | |
var canonicalUri = "/mqtt"; | |
var host = options.endpoint; | |
var credentialScope = | |
dateStamp + "/" + region + "/" + service + "/" + "aws4_request"; | |
var canonicalQuerystring = "X-Amz-Algorithm=AWS4-HMAC-SHA256"; | |
canonicalQuerystring += | |
"&X-Amz-Credential=" + | |
encodeURIComponent(accessKey + "/" + credentialScope); | |
canonicalQuerystring += "&X-Amz-Date=" + amzdate; | |
canonicalQuerystring += "&X-Amz-SignedHeaders=host"; | |
var canonicalHeaders = "host:" + host + "\n"; | |
var payloadHash = SigV4Utils.sha256(""); | |
var canonicalRequest = | |
method + | |
"\n" + | |
canonicalUri + | |
"\n" + | |
canonicalQuerystring + | |
"\n" + | |
canonicalHeaders + | |
"\nhost\n" + | |
payloadHash; | |
console.log("canonicalRequest " + canonicalRequest); | |
var stringToSign = | |
algorithm + | |
"\n" + | |
amzdate + | |
"\n" + | |
credentialScope + | |
"\n" + | |
SigV4Utils.sha256(canonicalRequest); | |
var signingKey = SigV4Utils.getSignatureKey( | |
secretKey, | |
dateStamp, | |
region, | |
service | |
); | |
var signature = SigV4Utils.sign(signingKey, stringToSign); | |
canonicalQuerystring += "&X-Amz-Signature=" + signature; | |
var sessionToken = options.sessionToken | |
? "&X-Amz-Security-Token=" + options.sessionToken | |
: ""; | |
return ( | |
"wss://" + host + canonicalUri + "?" + canonicalQuerystring + sessionToken | |
); | |
} | |
const mqtt = require("mqtt"); | |
// insert formatRequestUrl() result here: | |
const client = mqtt.connect( | |
formatRequestUrl({ | |
regionName: "us-west-2", | |
secretKey: "feedme", | |
accessKey: "feedme", | |
endpoint: "feedme", | |
}) | |
); | |
client.on("connect", function () { | |
console.log("CONN_ESTABLISHED"); | |
client.subscribe( | |
"$aws/things/my-device/shadow/name/Status/get/accepted", | |
function (err) { | |
if (!err) { | |
console.log("SUBSCR_ESTABLISHED", err); | |
client.publish("$aws/things/my-device/shadow/name/Status/get", ""); | |
} | |
} | |
); | |
}); | |
client.on("message", function (topic, message) { | |
console.log("MSG_RCVD", message); | |
// message is Buffer | |
console.log(topic, message.toString()); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dependencies": { | |
"crypto-js": "^4.1.1", | |
"moment": "^2.29.4", | |
"mqtt": "^4.3.7" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment