The code for generating SAS tokens with node could need an update as the new Buffer() API is long deprecated and should be replaced by Buffer.from(). The code that I can come up with is the following:
const crypto = require('crypto');
module.exports = (resourceUri, signingKey, expiresInMins, policyName = '') => {
const encodedResourceUri = encodeURIComponent(resourceUri.toLowerCase());
// Set expiration in seconds.
const expires = Math.ceil(Date.now() / 1000 + expiresInMins * 60);
// Sign the resource URI and the expiry time to verify authenticity.
const hmac = crypto
.createHmac('sha256', Buffer.from(signingKey, 'base64'))
.update(`${resourceUri}\n${expires}`);
const signature = encodeURIComponent(hmac.digest('base64'));
// Construct authorization string.
let token = 'SharedAccessSignature ';
token = `${token}sig=${signature}`;
token = `${token}&se=${expires}`;
if (policyName) {
token = `${token}&skn=${policyName}`;
}
token = `${token}&sr=${encodedResourceUri}`;
return token;
};
⚠Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
@nicklasfrahm Thanks for the feedback! We will investigate on this issue and get back to you soon.
Python is broken/outdated too "Unicode-objects must be encoded before hashing". Here is the offending line of code:
signature = b64encode(HMAC(b64decode(key), sign_key, sha256).digest())
@nicklasfrahm Thanks for bringing this to our attention. Would you like to create a PR with that code for the author to review? Or should we assign the issue to the content author to evaluate and fix it himself?
@Alberto-Vega-MSFT I'd love to, but my problem is that I do not have a test case or anything that I can use to verify my implementation. I could submit a PR, but it has to be verified by somebody, who knows how it is supposed to work.
taggint @wesmc7777 content author for awareness
@wesmc7777 Please check this and update the doc as appropriate.
Any update on this?
@nicklasfrahm -- thanks for your feedback.! I've spent a little time today on this:
Buffer.from() rather than new Buffer() in this line works just fine. After making the change in the existing topic code, I did successfully create a token and use it to open a registry client and make calls to list the devices registered with a hub. The new line should look like the following:node.js
var hmac = crypto.createHmac('sha256', Buffer.from(signingKey, 'base64'));
As noted, the same issue (and a couple of others) exist in the python code. The offending line needs to be changed from signature = b64encode(HMAC(b64decode(key), sign_key, sha256).digest()) to the following to properly encode the sign_key parameter:
signature = b64encode(HMAC(b64decode(key), sign_key.encode('utf-8'), sha256).digest())
NOTE: There seemed to be some other issues with the python code.
I'll create a PR to fix all of these and run it by our engineers for them to validate. I'll post again once we've published the updated topic. If I learn anything different in the interim, I'll let you know.
Thanks again for taking the time to alert us to this issue.
Hi @nicklasfrahm,
Thanks again for your feedback. I've updated the topic as noted above, and it's now been published: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-security#security-tokens . Please have a look and let me know if there is anything else. (I'll keep this issue open for the next couple of days.)
Thanks for the thumbs up @nicklasfrahm. I'll go ahead and close the issue.