2

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.

6
  • 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. Commented Sep 4, 2018 at 8:16
  • 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" }' Commented Sep 4, 2018 at 8:18
  • 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. Commented Sep 4, 2018 at 8:24
  • 1
    That api-version doesn't look right. Commented Sep 4, 2018 at 9:07
  • @evilSnobu Why? Commented Sep 4, 2018 at 9:24

1 Answer 1

1

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://learn.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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.