Shared Access Signature (SAS) for Service Bus introduces the new authentication and authorization model. With SAS, authentication and authorization can be
done without of need to involve Access Control Service which is the default authentication and authorization model when working with Service Bus.
I already shortly described this model in this post.
In this post I will provide two WORKING examples which show how to create SAS token in .NET and in JavaScript, respectively.
Creating of SAS token in .NET
Following code shows how to create SB-SAS token in C#.
var sasToken = createToken("http://yournamespace.servicebus.windows.net/yourqueue”, "device_send_listen", "…z67vRa9Tk8TJo0sErXlL6jg7P6dFA="); // Create REST request and append the token to ‘Authorization’ header . . . /// <summary> /// Code for generating of SAS token for authorization with Service Bus /// </summary> /// <param name="resourceUri"></param> /// <param name="keyName"></param> /// <param name="key"></param> /// <returns></returns> private static string createToken(string resourceUri, string keyName, string key) { TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1); var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h 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; }
|
To use this token you will have to create the REST request and append the token to ‘Authorization’ header. Fortunately nobody
in .NET space will do that, because .NET SDK provide much simpler way to deal with SAS tokens. However the sample above
shows how the token can be created if you need to talk to Service Bus by using of REST. For example, the code above helped me to
to understand how to make a token and to implement the same code in JavaScript.
Following example shows how to create SAS token implicitly in a much simpler way by using .NET SDK.
public static void SasTokenSample() { Uri runtimeUri = ServiceBusEnvironment.CreateServiceUri("sb", "yournamespace", string.Empty); MessagingFactory mf = MessagingFactory.Create(runtimeUri, TokenProvider.CreateSharedAccessSignatureTokenProvider("device_send_listen", "AsjoWKeRn5fiyELz67vRa9Tk8TJo0sErXlL6jg7P6dFA=")); QueueClient sendClient = mf.CreateQueueClient(m_qName); //Sending message to queue. BrokeredMessage helloMessage = new BrokeredMessage("Hello, Service Bus!"); helloMessage.MessageId = "Hello SAS token Message"; sendClient.Send(helloMessage); }
|
Creating of a SAS token in JavaScript
When you work in JavaScript, there is no Service Bus JS-SDK, which helps to create the token. For this reason I implemented a sample
which creates the SAS token for Service Bus in Java Script.
Before you start you will have to include Google’s crypto helpers HMAC-SHA256 and Base64.
<script type="text/javascript" src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/hmac-sha256.js"></script> <script type="text/javascript" src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/components/enc-base64-min.js"></script> |
Here is the JS code for SAS token creation:
var m_ServiceNamespace = “yournamespace”; var m_SasKey = "…ErXlL6jg7P6dFA="; var m_SasKeyName = "device_send_listen"; // Function which creates the Service Bus SAS token. var getToken = function (entityPath) { var uri = "http://" + m_ServiceNamespace + ".servicebus.windows.net/" + entityPath; var endocedResourceUri = encodeURIComponent(uri); var t0 = new Date(1970, 1, 1, 0, 0, 0, 0); var t1 = new Date(); var expireInSeconds = + (31*24*3600) + 3600 + (((t1.getTime() - t0.getTime()) / 1000) | 0); var plainSignature = utf8Encode(endocedResourceUri + "\n" + expireInSeconds); var hash = CryptoJS.HmacSHA256(plainSignature, m_SasKey); var base64HashValue = CryptoJS.enc.Base64.stringify(hash); var token = "SharedAccessSignature sr=" + endocedResourceUri + "&sig=" + encodeURIComponent(base64HashValue) + "&se=" + expireInSeconds + "&skn=" + m_SasKeyName; return token; } var utf8Encode = function (s) { for (var c, i = -1, l = (s = s.split("")).length, o = String.fromCharCode; ++i < l; s = (c = s.charCodeAt(0)) >= 127 ? o(0xc0 | (c >>> 6)) + o(0x80 | (c & 0x3f)) : s ); return s.join(""); }
|
And finally, following sample shows hot to send the message to Service Bus. When the user click on the button the message is read
from HTML TextBox named ‘btnSend’ and serialized as JSON.
sendMessage: function (entityPath, body, contentType, callback) { var securityToken = getToken(entityPath); var entityUri = "https://" + m_ServiceNamespace + "." + this.environment + "/" + entityPath; var sendUri = entityUri + "/messages/?timeout=60"; var xmlHttpRequest = new XMLHttpRequest(); xmlHttpRequest.open("POST", sendUri, true); xmlHttpRequest.setRequestHeader('Content-Type', contentType); xmlHttpRequest.setRequestHeader("Authorization", securityToken); xmlHttpRequest.onreadystatechange = function () { if (this.readyState == 4) { var messagingResult; // Expects HTTP-201 (Created) when the // message is entered in the queue / topic. if (this.status == 201) { messagingResult = new MessagingResult("Success", this.status, null, this.response); } else { messagingResult = new MessagingResult("Failure", this.status, null, this.response); } callback(messagingResult); } }; xmlHttpRequest.send(body); },
$("#btnSend").click(function () { msg = { "message": txtMsg.value, "id": 1234}; SB.sendMessage(queue, JSON.stringify(msg) , "application/json", function (messagingResult) { var res = messagingResult; }); }); |
In my following posts, I will describe how to receive this message on Windows RT and Windows system 32 (also know as Windows Desktop).
Posted
Oct 17 2013, 07:32 AM
by
Damir Dobric