1
votes

I am following this link in order to make an HTTP POST to an Eventhub in Azure. the error I am getting is 401 40103: Invalid authorization token signature. According to Azure, the POST should have the following format:

POST https://your-namespace.servicebus.windows.net/your-event-hub/partitions/0/messages?timeout=60&api-version=2014-01 HTTP/1.1  
Authorization: SharedAccessSignature sr=your-namespace.servicebus.windows.net&sig=your-sas-key&se=1403736877&skn=RootManageSharedAccessKey  
Content-Type: application/atom+xml;type=entry;charset=utf-8  
Host: your-namespace.servicebus.windows.net  

Regarding the Authorization header, I have several questions:

  1. My secret key (sig) has an equal sign, should I substitute it by %3d?
  2. I am currently doing also the POST operation with the example scripts in Python and C from Azure. In these examples, is only required to introduce the endpoint with all the credentials and the post/get operations works fine. Is it possible to perform the put/get operations introducing directly the endpoint in the api rest, or obtaining the authorization header that is performed bellow the python or c code?

Thanks.

1
Can you please show what POST you are currently doing from REST? The reason why the C and Python APIs work is because they build the REST request under the hood.ranieuwe
Sure! This is currently my POST message curl -X POST -k -H 'Content-Type: application/atom+xml;type=entry;charset=utf-8' -H 'Authorization: SharedAccessSignature sr=mynamespace.servicebus.windows.net&sig=mysignature&se=1803736877&skn=RootManageSharedAccessKey' -i 'mynamespace.servicebus.windows.net/myeventhub/…' --data '{ "DeviceId":"dev-01", "Temperature":"37.0" }'qwerty
That looks correct. Regarding your first question, + with %3d, it should be encoded I believe, so yes best to do that. Also make sure your expiry (the se field) is not set to something in the past. That would also cause the 401.ranieuwe
That api-version doesn't look right.evilSnobu
@evilSnobu Why?qwerty

1 Answers

1
votes

I'm able to make it work by creating a SAS policy (nssend below) on the namespace, not on the Event Hub.

$ curl -X POST -i "https://breakingnews.servicebus.windows.net/sucheventsmuchwow/messages" \
    -H "Authorization: SharedAccessSignature sr=https%3A%2F%2Fbreakingnews.servicebus.windows.net%2Fsucheventsmuchwow%2Fmessages&sig=SAS_SIG_GOES_HERE&se=1536733370&skn=nssend" \
    -H "Content-Type: application/json" \
    --data-ascii "{ \"message\": \"So many events, so little time.\" }"


HTTP/1.1 201 Created
Server: Microsoft-HTTPAPI/2.0
...

So that works.

However, i'm getting a HTTP 401, just like you are, when using an Event Hub level SAS policy to generate the signature (as opposed to a namespace level policy).

This is what i used to generate the SAS token —

// Make a SAS token
// See https://docs.microsoft.com/en-us/rest/api/eventhub/generate-sas-token
// Appologies for JavaScript
// npm install moment

const moment = require('moment');
const crypto = require('crypto');

function create_sas_token(uri, key_name, key)
{
    // Token expires in one hour
    var expiry = moment().add(7, 'days').unix();

    var string_to_sign = encodeURIComponent(uri) + '\n' + expiry;
    var hmac = crypto.createHmac('sha256', key);
    hmac.update(string_to_sign);
    var signature = hmac.digest('base64');
    var token = 'SharedAccessSignature sr=' +
        encodeURIComponent(uri) +
        '&sig=' + encodeURIComponent(signature) +
        '&se=' + expiry + '&skn=' + key_name;

    return token;
}

let token = create_sas_token('https://breakingnews.servicebus.windows.net/sucheventsmuchwow/messages', 'MySendPolicy', 'MySendPolicyPrimaryKey=');

console.log(token);

UPDATE

Thanks to Clemens Vasters —

Try omitting "/messages"

— Clemens Vasters 📨, Messenger (@clemensv) September 5, 2018

Your string to sign (resource URI) should omit /messages, e.g.

create_sas_token('https://breakingnews.servicebus.windows.net/sucheventsmuchwow',
    'MyEventHubLevelPolicy', 'hUbPriMAry/KEy=');

then craft your request as follows —

$ curl -X POST -i "https://breakingnews.servicebus.windows.net/sucheventsmuchwow/messages" \
    -H "Authorization: SharedAccessSignature sr=https%3A%2F%2Fbreakingnews.servicebus.windows.net%2Fsucheventsmuchwow&sig=DONT_INCLUDE_/MESSAGES_IN_STRING_TO_SIGN&se=1536757127&skn=MyEventHubLevelPolicy" \
    -H "Content-Type: application/json" \
    --data-ascii "{ \"message\": \"SAS signed with Event Hub level policy\" }"


HTTP/1.1 201 Created
Server: Microsoft-HTTPAPI/2.0
...

TL;DR:

Your POST URL should include the trailing /messages, but the string to sign (resource URI) should not. Always. Regardless if using Namespace or Hub-scoped policy.