16

The Azure Queues are exposed to REST API.To make the REST call works. I ran a sample test on POSTMAN. The POST call

https://yournamespace.servicebus.windows.net/yourentity/messages

Also, Passing below 2 headers and values.

Header 1:

Authorization: SharedAccessSignature sr=https%3A%2F%2F.servicebus.windows.net%2Fyourentity&sig=yoursignature from code above&se=1529928563&skn=KeyName

Example:

SharedAccessSignature sr=https%3A%2F%2Fservicebussoatest1.servicebus.windows.net%2Fpublishque&sig=a0wmRklbCGFCYoSCViij9gagtZV9Bg+vU=&se=1529928563&skn=testpolicy

Header 2:

Content-Type: application/json

But even though I have passed the correct Authorization value, I am getting the error below:

401:Invalid Authorization Token signature

CDspace
  • 2,639
  • 18
  • 30
  • 36
user3796942
  • 163
  • 1
  • 1
  • 6

3 Answers3

23

401:Invalid Authorization Token signature

According to the 401 error meanings that the token is not vaild.

Firstly please make sure that your policy has access to send the message.

Secondly, if you want to use the azure service bus Send Message Rest APi. The format should be following.

POST https://<yournamespace>.servicebus.windows.net/<yourentity>/messages
Authorization: SharedAccessSignature sr=https%3A%2F%2F<yournamespace>.servicebus.windows.net%2F<yourentity>&sig=<yoursignature from code above>&se=1438205742&skn=KeyName
ContentType: application/atom+xml;type=entry;charset=utf-8

We also could get more information about Service Bus access control with Shared Access Signatures from this article.

I also do a demo with postman. It works correctly on my side.

I use the following code to get the SAS token.

public static string GetSasToken(string resourceUri, string keyName, string key, TimeSpan ttl)
{
      var expiry = GetExpiry(ttl);
      string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
      HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
      var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
      var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
      HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
      return sasToken;
}

private static string GetExpiry(TimeSpan ttl)
{
    TimeSpan expirySinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1) + ttl;
    return Convert.ToString((int)expirySinceEpoch.TotalSeconds);
}
string queueUrl = "https://tomtestsb.servicebus.windows.net/" + "queue" + "/messages";
string token = GetSasToken(queueUrl,"Key", "value", TimeSpan.FromDays(1));

We could get the key and value with Azure portal

enter image description here

Test it with Postman.

Headers:

Authorization:SharedAccessSignature sr=https%3a%2f%2fyournamespace.servicebus.windows.net%2fqueuename%2fmessages&sig=SyumAUNnqWFjW2MqjwlomU%2fbblqZljq6LPJp3jpfU%2b4%3d&se=1529478623&skn=KeyName

Content-Type:application/xml

Body

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">This is a message.</string> 

Test Result:

enter image description here

Tom Sun - MSFT
  • 24,161
  • 3
  • 30
  • 47
  • To Receive messages from Service Bus Queue,We will perform DELETE operation (Receive and Delete messages from Queue) on REST api.My question is ,How we can listen frequently messages from the Queue.As soon as the messages placed into the queue our REST service should pickup the message instead of invocation of REST call. – user3796942 Jun 21 '18 at 05:45
  • If Azure function is possible, I suggest that you could use the [Azure function with service bus binding](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus) to do that. – Tom Sun - MSFT Jun 21 '18 at 06:00
  • 2
    Note: when I tried to use the shared access polices on the queue it would fail with authorization token error, however if I use the shared access polices on the service bus namespace it works. – Nicholas Feb 21 '19 at 06:51
  • 1
    When you say `Firstly please make sure that your policy has access to send the message`, can you give a bit more details as to what you mean? – atamata Nov 19 '20 at 12:19
  • 1
    Great answer, worked for me! If you want very long lasting tokens (for me: 100 years), replace return Convert.ToString((int)expirySinceEpoch.TotalSeconds); with return Convert.ToString((long)expirySinceEpoch.TotalSeconds); – Benjamin Jun 03 '21 at 14:31
1

Simple 2 step process:

First you can import the below Curl in postman:

curl --location --request POST '{{topicQueueForAzureServiceBusUri}}' \
--header 'ContentType: application/atom+xml;type=entry;charset=utf-8' \
--header 'Authorization: {{SasTokenForAzureServiceBus}}' \
--header 'Content-Type: application/json' \
--data-raw '{"YOUR JSON"}'

Copy All the key generation script to the prerequisite step of Postman Request and replace first four variable values from your topic/queue config:

var namespace = "YOUR Namespace";
var topicQueueName = "YOUR TOPIC/QUEUE Name";
var sharedAccessKeyName = "YOUR sharedAccessKeyName";
var sharedAccessKey = "YOUR sharedAccessKey";

var topicQueueForAzureServiceBusUri = "https://" + namespace + ".servicebus.windows.net/" + topicQueueName + "/messages";
pm.collectionVariables.set("topicQueueForAzureServiceBusUri", topicQueueForAzureServiceBusUri);
var sasToken = createSharedAccessToken(topicQueueForAzureServiceBusUri, sharedAccessKeyName, sharedAccessKey);
pm.collectionVariables.set("SasTokenForAzureServiceBus", sasToken);

function createSharedAccessToken(uri, saName, saKey) { 
    if (!uri || !saName || !saKey) { 
            throw "Missing required parameter"; 
        } 
    var encoded = encodeURIComponent(uri).toLowerCase(); 
    var now = new Date(); 
    var week = 60*60*24*7;
    var ttl = Math.round(now.getTime() / 1000) + week;
    var signature = encoded + '\n' + ttl;     
    var hash = CryptoJS.HmacSHA256(signature, saKey);
    var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
    return 'SharedAccessSignature sr=' + encoded + '&sig=' +  
        encodeURIComponent(hashInBase64) + '&se=' + ttl + '&skn=' + saName; 
}
Anand Varkey Philips
  • 1,811
  • 26
  • 41
0

This worked for me:

The url to POST to: https://[ServiceBusNamespace].servicebus.windows.net/[QueueName]/messages

Authorization: use code provided by Tom Sun - MSFT

Content-Type: application/json

Adrian
  • 19
  • 2