Create registration for Azure Notification Hub in Postman
Asked Answered
D

10

16

I created a Service Bus / Notification Hub in my Azure Portal.

Now I'm trying to use the Azure REST API with Postman based on this doc : https://msdn.microsoft.com/en-us/library/azure/dn223265.aspx

Here is the Postman configuration I have :

It's a POST method of the following url (Create Registration) https://mysite.servicebus.windows.net/mysite-notif/registrations/?api-version=2015-01 (I replaced with mysite in that url for privacy reasons)

In the Headers, I typed 2 entries :

Content-Type application/atom+xml;type=entry;charset=utf-8

Authorization Endpoint=sb://[mysite].servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=[mykey] (this Connection information I copied from the Azure portal)

In the Body, I chose raw - XML(txt/xml) and pasted :

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom">
    <content type="application/xml">
        <WindowsRegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">
            <Tags>myTag, myOtherTag</Tags>
            <ChannelUri>{ChannelUri}</ChannelUri>
        </WindowsRegistrationDescription>
    </content>
</entry>

(it's the Native registration for Windows Notification Service example)

When I send this call from within Postman, I get a 401 Error :

<Error>
    <Code>401</Code>
    <Detail>MalformedToken: The credentials contained in the authorization header are not in the WRAP format..TrackingId:ee0d87ef-6175-46a1-9b35-6c31eed6049d_G2,TimeStamp:8/13/2015 9:58:26 AM</Detail>
</Error>

What am I missing ? Is it the Authorization tab I left on "No Auth" in Postman ? Is it the value of the Authorization header that should be encoded like shown here ? Creating registration ID for Azure Notification Hub via REST api

Thanks.

Declamation answered 13/8, 2015 at 12:25 Comment(0)
K
9

Your "Authorization" header is not correct.

As stated in the Azure Notification Hubs REST API documentation, e.g. for creating a registration, the "Authorization" header has to contain the "Token generated as specified in Shared Access Signature Authentication with Service Bus"...

The token format is specified in the documentation for Shared Access Signature Authentication with Service Bus as the following:

SharedAccessSignature sig=<signature-string>&se=<expiry>&skn=<keyName>&sr=<URL-encoded-resourceURI>
  • URL-encoded-resourceURI: The url you send the POST request to (in your case "https://mysite.servicebus.windows.net/mysite-notif/registrations/?api-version=2015-01")
  • keyName: In your case the default key name "DefaultFullSharedAccessSignature"
  • expiry: The expiry is represented as the number of seconds since the epoch 00:00:00 UTC on 1 January 1970.
  • signature-string: The signature for the SAS token is computed using the HMAC-SHA256 of a string-to-sign with the PrimaryKey property of an authorization rule. The string-to-sign consists of a resource URI and an expiry, formatted as follows:
    • StringToSign = <resourceURI> + "\n" + expiry;
    • resourceURI should be the same as URL-encoded-resourceURI (also URL encoded)
    • Compute the HMAC-SHA256 of StringToSign using the SAS key (what you replaces with [mykey] in your example). Use the URL encoded result for signature-string then.
Krp answered 14/8, 2015 at 15:25 Comment(7)
I used your information to correct my code (which is Javascript in Adobe Campaign/Neolane) I get a 401 "HTTP header 'WWW-Authenticate' used for proxy authentication not found." The 4 parameters obtained to build the SharedAccessSignature are : 1) signatureString : 201970e7eaec1c11764c29185575e051a5b447fc63256b319e5bb624677fd8cb - 2) expiry : 1441035401.512 - 3) keyName : DefaultFullSharedAccessSignature - 4) URL-encoded-resourceURI : mysite-ns.servicebus.windows.net/mysite/registrations/… Does it look correct ? (apparently not though)Sup
Fix to show full url: URL-encoded-resourceURI : https:// mysite-ns.servicebus.windows.net/mysite/registrations/?api-version=2015-01 (w/o space inside)Sup
1. expiry should be an integer (you have a dot there). 2. Your URI is not URL encoded (should be this: https%3A%2F%2Fmysite-ns.servicebus.windows.net%2Fmysite%2Fregistrations%2F%3Fapi-version%3D2015-01). 3. About the error you get: It seems you have some proxy configured, I don't know how that works, but have a look at this question.Krp
I computed my token based on Creating registration ID for Azure Notification Hub via REST api Token : SharedAccessSignature sr=https%3a%2f%2fmyhubnotif-ns.servicebus.windows.net%2fmyhubnotif%2fregistrations%2f%3fapi-version%3d2015-01&sig=91336b70ff4933ebddad687d9350bb0c9b65806a1997750b8b6d78271a185413&se=1449128177&skn=DefaultFullSharedAccessSignature - In Postman, Authorization header with that token returns 401 40103 : Invalid authorization token signature - Still no luckSup
Your SAS token looks OK to me. Double check, if you used to correct key and hub.Krp
I ended up generating the token below in .NET with that code sample then manually gave it to my Javascript code. The HttpClientRequest went through. I'll come back later to that token/401 issue, thanks - SharedAccessSignature sr=https%3a%2f%2fvphubnotif-ns.servicebus.windows.net%2fvphubnotif%2fregistrations%2f&sig=MNhR6Wn%2b2kDaD6Ik6gbbZWrKyAjdKxYZq73NsDOaKkQ%3d&se=1441700857&skn=DefaultFullSharedAccessSignatureSup
@2020 - AzureServiceBus REST API in C# .NET core using HTTPClient - this worked for me stackoverflow.com/a/45055279Catalysis
E
17

Here is an example of a pre-request script for postman that generates the needed header:

function getAuthHeader(resourceUri, keyName, key) {

    var d = new Date();
    var sinceEpoch = Math.round(d.getTime() / 1000);

    var expiry = (sinceEpoch + 3600);

    var stringToSign = encodeURIComponent(resourceUri) + '\n' + expiry;

    var hash = CryptoJS.HmacSHA256(stringToSign, key);
    var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);

    var sasToken = 'SharedAccessSignature sr=' + encodeURIComponent(resourceUri) + '&sig=' + encodeURIComponent(hashInBase64) + '&se=' + expiry + '&skn=' + keyName;

    return sasToken;
}

postman.setEnvironmentVariable('azure-authorization', getAuthHeader(request['url'], "mySharedAccessKeyName", "mySharedAccessKey"));
postman.setEnvironmentVariable('current-date',new Date().toUTCString());

To use it do the following:

  1. add this pre-request script to your postman request
  2. replace mySharedAccessKeyName , mySharedAccessKey with your credentials
  3. add a header Authorization: {{azure-authorization}}
  4. add a header x-ms-date: {{current-date}}
Elvinelvina answered 15/5, 2018 at 6:2 Comment(2)
This is not working for me, I get a generic response Publicly Listed Services, no matter what I use. Can you help out?Prussiate
Works perfect. Just use setGlobalVariable instead of setEnvironmentVariable if you don't have an environment configuration!Denitadenitrate
K
9

Your "Authorization" header is not correct.

As stated in the Azure Notification Hubs REST API documentation, e.g. for creating a registration, the "Authorization" header has to contain the "Token generated as specified in Shared Access Signature Authentication with Service Bus"...

The token format is specified in the documentation for Shared Access Signature Authentication with Service Bus as the following:

SharedAccessSignature sig=<signature-string>&se=<expiry>&skn=<keyName>&sr=<URL-encoded-resourceURI>
  • URL-encoded-resourceURI: The url you send the POST request to (in your case "https://mysite.servicebus.windows.net/mysite-notif/registrations/?api-version=2015-01")
  • keyName: In your case the default key name "DefaultFullSharedAccessSignature"
  • expiry: The expiry is represented as the number of seconds since the epoch 00:00:00 UTC on 1 January 1970.
  • signature-string: The signature for the SAS token is computed using the HMAC-SHA256 of a string-to-sign with the PrimaryKey property of an authorization rule. The string-to-sign consists of a resource URI and an expiry, formatted as follows:
    • StringToSign = <resourceURI> + "\n" + expiry;
    • resourceURI should be the same as URL-encoded-resourceURI (also URL encoded)
    • Compute the HMAC-SHA256 of StringToSign using the SAS key (what you replaces with [mykey] in your example). Use the URL encoded result for signature-string then.
Krp answered 14/8, 2015 at 15:25 Comment(7)
I used your information to correct my code (which is Javascript in Adobe Campaign/Neolane) I get a 401 "HTTP header 'WWW-Authenticate' used for proxy authentication not found." The 4 parameters obtained to build the SharedAccessSignature are : 1) signatureString : 201970e7eaec1c11764c29185575e051a5b447fc63256b319e5bb624677fd8cb - 2) expiry : 1441035401.512 - 3) keyName : DefaultFullSharedAccessSignature - 4) URL-encoded-resourceURI : mysite-ns.servicebus.windows.net/mysite/registrations/… Does it look correct ? (apparently not though)Sup
Fix to show full url: URL-encoded-resourceURI : https:// mysite-ns.servicebus.windows.net/mysite/registrations/?api-version=2015-01 (w/o space inside)Sup
1. expiry should be an integer (you have a dot there). 2. Your URI is not URL encoded (should be this: https%3A%2F%2Fmysite-ns.servicebus.windows.net%2Fmysite%2Fregistrations%2F%3Fapi-version%3D2015-01). 3. About the error you get: It seems you have some proxy configured, I don't know how that works, but have a look at this question.Krp
I computed my token based on Creating registration ID for Azure Notification Hub via REST api Token : SharedAccessSignature sr=https%3a%2f%2fmyhubnotif-ns.servicebus.windows.net%2fmyhubnotif%2fregistrations%2f%3fapi-version%3d2015-01&sig=91336b70ff4933ebddad687d9350bb0c9b65806a1997750b8b6d78271a185413&se=1449128177&skn=DefaultFullSharedAccessSignature - In Postman, Authorization header with that token returns 401 40103 : Invalid authorization token signature - Still no luckSup
Your SAS token looks OK to me. Double check, if you used to correct key and hub.Krp
I ended up generating the token below in .NET with that code sample then manually gave it to my Javascript code. The HttpClientRequest went through. I'll come back later to that token/401 issue, thanks - SharedAccessSignature sr=https%3a%2f%2fvphubnotif-ns.servicebus.windows.net%2fvphubnotif%2fregistrations%2f&sig=MNhR6Wn%2b2kDaD6Ik6gbbZWrKyAjdKxYZq73NsDOaKkQ%3d&se=1441700857&skn=DefaultFullSharedAccessSignatureSup
@2020 - AzureServiceBus REST API in C# .NET core using HTTPClient - this worked for me stackoverflow.com/a/45055279Catalysis
C
4

After spending over an hour trying to understand why the steps above didn't work, I realized if you are using the code from https://code.msdn.microsoft.com/Shared-Access-Signature-0a88adf8 It has two things that are not defined at the top of the code. Key and KeyName.

The Key is the part that alluded me because at first glance on the other post here I thought it was the same. Its not.

In Azure: Go to your Notification Hub, Then Click > Settings> Access Policies then on the Policy that has Manage Permission. Add a policy if you need to. Once you Click on the Access Policy. It shows Connection String, Primary and Secondary. Copy the Primary to your Clipboard and throw it in notepad. It will look something like this..

Endpoint=sb://mysite.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=hc7qZ+pMG6zltjmASDFrskZO+Yv52D55KQUxUTSO0og=

SharedAccessKeyName = KeyName

SharedAccessKey = Key

Yea it looks obvious all spelled out here but you cannot see this information in AZURE portal unless you copy it.

So Just to be totally Clear, in the header you generate the key "sig" by combining + "\n" + expiry which Baris did point out, but then you sign it with the Key not the KeyName..

I may sounds like an idiot spelling this out but this process is not an easy one.

Hope it helps someone else.

Chrisman answered 3/10, 2016 at 20:34 Comment(2)
Oh God I'm an idiot. Thank you for this. I was using the wrong key.Signboard
The SharedAccessKey format you specified here with Endpoint=sb and two keys is valid only when making Azure Service Bus call with sb protocol (native) and not when using its REST APIs. Or you would get error similar to "The credentials contained in the authorization header are not in the WRAP format"Catalysis
G
1

Baris Akar's response is mostly correct, except for one omission that, for whatever reason, is also not mentioned in the relevant documentation: the signature parameter (i.e., the signature-string in sig=) must be Base64 encoded!

Greenheart answered 4/4, 2018 at 12:39 Comment(0)
D
1

You have to remove "\"" in Token String like below.

authorizationString = resultA.replaceAll("\"","");

From "SharedAccessSignature sr=https%3a%2f%2fmshub.servicebus.windows.net%2f&sig=PFZVab43PMsO0q9gz4%2bFsuaQq%5ff05L4M7hKVBN8DEn0%3d&se=1553339810&skn=RootManageSharedAccessKey"

To SharedAccessSignature sr=https%3a%2f%2fmshub.servicebus.windows.net%2f&sig=PFZVab43PMsO0q9gz4%2bFsuaQq%5ff05L4M7hKVBN8DEn0%3d&se=1553339810&skn=RootManageSharedAccessKey

Good luck.

Doll answered 6/4, 2018 at 3:9 Comment(0)
I
1

See the following documentation from Microsoft to generate a SAS Token. This token you can use in Postman.

Generate SAS Token (NodeJs, Java, etc.)

Incumber answered 8/6, 2021 at 12:13 Comment(0)
I
1

Working from D-rk's code, which is probably outdated in 2022, here's an updated version that works in Postman 10.5.6 and with the Azure Notification Hub's api-version 2020-06

Postman Pre-Request Script:

function createSharedAccessToken(sb_name, eh_name, saName, saKey) {
    if (!sb_name || !eh_name || !saName || !saKey) { 
        throw "Missing required parameter"; 
    } 
    var resourceUri = encodeURIComponent("https://" + sb_name + ".servicebus.windows.net/" + eh_name)

    // Set expiration in seconds
    var expires = (Date.now() / 1000) + 20 * 60;
    expires = Math.ceil(expires);
    var toSign = CryptoJS.enc.Utf8.parse(resourceUri + '\n' + expires);

    var sa_key_utf8 = CryptoJS.enc.Utf8.parse(saKey);

    var hmac = CryptoJS.HmacSHA256(toSign, sa_key_utf8);
    var hmacBase64 = CryptoJS.enc.Base64.stringify(hmac);
    var hmacUriEncoded = encodeURIComponent(hmacBase64);

    // Construct autorization string
    var token = "SharedAccessSignature sr=" + resourceUri + "&sig=" + hmacUriEncoded + "&se=" + expires + "&skn="+ saName;
    return token;
}

var sb_name = "your-notification-hub-namespace";
var eh_name = "your-notification-hub-name";
//See Access Policies -> Connection String
var sa_name = "your-shared-access-key-name"
var sa_key = "your-shared-access-key-name"

var auth_header = createSharedAccessToken(sb_name, eh_name, sa_name,sa_key);

pm.environment.set('azure-authorization',auth_header);
pm.environment.set('current-date',new Date().toUTCString());

Introversion answered 7/12, 2022 at 19:38 Comment(1)
Thank you!! This is working with the latest version of PostmanAthlete
M
0

Like Jérôme, I also used the example at https://code.msdn.microsoft.com/Shared-Access-Signature-0a88adf8 to generate the token and I also found out that the .NET-generated token worked. I compared the .NET-generated token with my ruby-generated token and found that URI.escape did not encode the last character (an '=' sign) of my base64 hash. It also did not encode '+' signs. Adding the string '=+' to the function fixed the problem: URI.escape(hmacb64, '=+') (I don't know if there are other characters that should be identified here.)

Marplot answered 15/6, 2016 at 9:55 Comment(0)
C
0

It also took me quite some time to figure out a way to generate the SAS tokens in Go.

I created a gist which shows how to generate those tokens: https://gist.github.com/dennis-tra/14c63e6359f17cbb504e78d6740ca465

I probably wouldn't have figured it out if had not found this repo: https://github.com/shanepeckham/GenerateSASTokenGo/blob/master/gosas.go

Canakin answered 10/1, 2019 at 8:18 Comment(0)
B
-1

Solution provided by Dirk helped me to resolve the issue. But make sure to use SharedAccessKeyName and SharedAccessKey from a policy which has "Manage" claims access. If you have only Send and/or Listen claims, then the authentication will not work and throws an error - MalformedToken: The credentials contained in the authorization header are not in the WRAP format

Boracic answered 22/11, 2019 at 23:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.