I am implementing REST-API for deleting key/entity from table in azure datastore, but seems it has issue in authorization token, and i think there is issue in making 'stringTosign' i.e. 'Signature' in azure. Below are code,
const key = {
"Namespace": "my-app",
"Path": [
{
"Kind": 'tblxyz',
"Name": "test-datastore-row"
}
]
};
REST Implementation:
public async DeleteAPI(key: Key): Promise<any> {
const tableService = await this.GetTableServiceAsync(); // gives me table metadata
const url = "https://" + tableService.storageAccount + ".table.core.windows.net/" + 'tblxyz' + '(PartitionKey=' + '\'' + key.Namespace + '\'' + ',' + 'RowKey=' + '\'' + key.Path[0].Name + '\'' + ')';
const timestamp = (new Date()).toUTCString();
const stringToSign = timestamp + '\n/' + tableService.storageAccount + '/' + 'tblxyz';
const hmac = crypto.createHmac('sha256', new Buffer(tableService.storageAccessKey, 'base64'))
.update(stringToSign, 'utf-8')
.digest('base64');
return new Promise((resolve, reject) => {
request.delete({
'headers': {
'Authorization': 'SharedKeyLite ' + tableService.storageAccount + ':' + hmac,
'x-ms-date': timestamp,
'x-ms-version': '2016-05-31',
'Content-Type': 'application/json',
'If-Match': '*'
},
'url': url,
'json': true
}, function (err, result) {
if (err) {
console.log('inside delete err', JSON.stringify(err));
return reject(err);
}
if (result.statusCode !== 200 && result.statusCode !== 204) {
console.log('inside delete err: 2', JSON.stringify(result));
return reject(result.body);
}
return resolve();
});
});
}
while making call to this API, i am getting below error,
Anybody have face this problem? Need help ...!!!!
Error message:
Error: the object {
"odata.error": {
"code": "AuthenticationFailed"
"message": {
"lang": "en-US"
"value": "Server failed to authenticate the request. Make sure the value
of Authorization header is formed correctly including the
signature.\nRequestId:df933tt7-0002-0004-41c3-782e5g000000\nTime:2017-12-
19T12:16:37.5434074Z"
}
}
} was thrown, throw an Error :)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
It seems there's an issue with your stringToSign
. Based on the documentation, it should include resource's encoded URI path. Can you try with the following:
const stringToSign = timestamp + '\n/' + tableService.storageAccount + '/' + 'tblxyz' + '(PartitionKey=' + '\'' + key.Namespace + '\'' + ',' + 'RowKey=' + '\'' + key.Path[0].Name + '\'' + ')';
UPDATE
Please see this sample code. Essentially the resource's path should be URL encoded:
const request = require("request");
const crypto = require("crypto");
const url = require('url');
var accountName = "account-name";
var accountKey = "account-key";
var tableName = "table-name";
var pk = "partition-key-value";
var rk = "row-key-value";
const encodedUriPath = tableName + '(PartitionKey=' + '\'' + pk + '\'' + ', ' + 'RowKey=' + '\'' + rk + '\'' + ')';
const endpoint = "https://" + accountName + ".table.core.windows.net/" + encodedUriPath;
const parsedUrl = url.parse(endpoint);
const timestamp = (new Date()).toUTCString();
console.log(url);
console.log(timestamp);
const stringToSign = timestamp + '\n/' + accountName + parsedUrl.path;
console.log('--------------------------------------');
console.log(stringToSign);
const hmac = crypto.createHmac('sha256', new Buffer(accountKey, 'base64'))
.update(stringToSign, 'utf-8')
.digest('base64');
console.log('--------------------------------------');
console.log(hmac);
request.delete({
'headers': {
'Authorization': 'SharedKeyLite ' + accountName + ':' + hmac,
'x-ms-date': timestamp,
'x-ms-version': '2016-05-31',
'Content-Type': 'application/json',
'If-Match': '*'
},
'url': endpoint,
'json': true
}, function (err, result) {
if (err) {
console.log('inside delete err', JSON.stringify(err));
} else {
console.log(JSON.stringify(result));
}
});