Will Perry is an engineer at Microsoft working on the Windows Azure Service Bus in Seattle. He’s also Co-Chair for Microsoft’s LGBT Employee Resource Group, GLEAM. In his free time, you can often find him hiking, at the ProClub or chilling-out on Capitol Hill.
As part of the Windows Azure Toolkit for Windows 8, we recently released a sample library for accessing Service Bus from Windows 8 metro style applications and a sample metro app demonstrating how to use some basic Service Bus functionality. In this post, we'll take a quick tour around the sample app, get an introduction to the sample library and examine in detail how the sample library works.
To help make getting started really easy, we've built the Service Bus Sample Browser for Windows 8 - this simple metro style application lets you explore and learn about service bus functionality interactively and always keeps you close to the code.
In every sample, bringing up the AppBar in the sample browser (Right Click with a Mouse, or swipe up from the bottom bezel with touch) will allow you to Copy Source Code from the sample to the clipboard for use in Visual Studio.
When you launch the sample browser, you'll find 3 simple samples included:
Simple Queues
Service Bus Queues are durable First In, First Out message queues that permit communication between distributed applications or components. You can learn more about Service Bus queues on WindowsAzure.com. The pattern for using queues is straightforward: someone sends a message to the queue, someone else receives the message later.
In the Simple Queues sample, you can follow a simple example of how to use this messaging pattern within a Windows 8 metro style application.
Simple Topics
Topics and Subscriptions in Service Bus support a publish/subscribe communication model - messages are Sent to a single topic and can then be Received by multiple subscribers. You can learn more about Service Bus Topics on WindowsAzure.com. Using topics is as simple as using queues - someone sends a message to the topic and each subscriber is able to receive a copy of that message later.
In the Simple Topics sample you'll create a Topic, add one or more subscribers to it then send and receive messages.
Peek Lock, Abandon and Complete
Both Queues and Subscriptions support to different ways to receive messages. The first, Receive and Delete, removes the message from the queue or subscription when it is received - if the receiver fails to process the message, then its content is lost. The second, Peek Lock, makes the Receive and Delete operations two separate operations - first a messages is Peeked from the queue by the receiver, later the receiver can Complete the message (deleting it from the queue or subscription and marking it as processed) or Abandon the message (marking it as not completed or unprocessed). A message is returned to the queue or subscription if it is abandoned of its peek-lock times out (by default, the peek lock timeout is 30 seconds).
In the Peek Lock Sample, you try out peek locking yourself. Click each of the shapes to send it to a queue and then try receiving. When you've received a shape, select it to Complete or Abandon the message - Completed messages do not return to the Queue, while abandoned ones do. If you neither complete or abandon a message, you'll observe that it's lock expires and it is automatically returned to the queue.
To get started download the Windows Azure Toolkit for Windows 8.
To make it easier to consume the Service Bus REST API, we've built a sample library for Windows 8 which wraps common Service Bus primitives like Queue, Topic and Subscription - let's dive straight into some code to illustrate creating a queue, sending a message, receiving the message and deleting the queue. If you are new to the Service Bus, take a look at these how-to articles on Service Bus Queues and Service Bus Topics.
Since we'll be calling Service Bus over HTTP, we need to consider a couple of things:
First up, we need a Token Provider. Token Providers are used by the library to request an authorization token from the Access Control Service (ACS) and attach that token to requests made to Service Bus. You can think of the Token Provider like a set of credentials - it specifies 'who' is trying to perform an action on a service bus resource:
TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(
serviceNamespace: "Your Service Bus Namespace Name, e.g. contoso",
issuerName: "owner",
issuerSecret: "Your Service Bus Issuer Secret, e.g. b66Gxx...");
Next we'll create a queue - this super-simple call specifies the path of the queue to create and uses the default queue description. If you want to tweak the settings on the queue you're creating, you'll find a helpful overload accepting a Queue Description as a parameter:
Queue myQueue = await Queue.CreateAsync("MyQueue", tokenProvider);
With the queue created in Service Bus, we can go ahead and send a message. The samples library makes it simple to send plain text messages or messages whose body is a JSON formatted object. Here, we're just going to asynchronously send a plain text string as the body of the message:
await myQueue.SendAsync("Hello World!");
Receiving a message is just a simple - we'll attempt to receive from the queue using Receive and Delete semantics. If you want to use Peek Lock semantics, you'll find the PeekLockAsync method nearby. Having received the message, we'll extract the plain-text body:
BrokeredMessage message = await myQueue.ReceiveAndDeleteAsync();
string greeting = message.GetBody<string>();
Finally, we're going to clean up after ourselves and delete the queue:
await Queue.DeleteAsync("MyQueue", tokenProvider);
So, there we go - just a few lines of code to create, send, receive and delete entities in Service Bus. In the Sample Service Bus Library for Windows 8, we've tried to ensure you have a simple API surface area to get started with and the full power of our REST API surface available when you want it. We're shipping this library as an open source licensed sample to give you the freedom and flexibility to dive deep into the code if you want to and tweak to your heart's content!
We're hopeful that the simplified API surface in the Sample Service Bus Library for Windows 8 makes it easy to get started building great Metro Style Apps that are connected with Service Bus - we've tried to reduce the total number of concepts you need to become familiar with to achieve typical scenarios and make it easier to learn about our advanced features as you need them - we're always keen to hear your feedback on how useful this sample library is to you, please let us know you thoughts on the discussion list for Windows Azure Toolkit for Windows 8.
Service bus operations fall into one of two classes: Management or Runtime. Management operations are used to Create, Enumerate, Get and Delete service bus entities like Queues, Topics and Subscriptions; Runtime operations are used to Send and Receive messages. Firstly we'll dive deep into how the Sample Service Bus Library for Windows 8 implements Management Operations, and then we'll take a look at how Runtime Operations are implemented.
Management Operations: Create, Get, Enumerate and Delete
The service bus namespace can be thought of as a set of ATOM Feeds, each describing entities that exist at paths beneath it. For example, if a Queue called 'Foo' exists at the Uri: https://contoso.servicebus.windows.net/Foo then we would find an atom entry like this at that address:
Quickly looking over the markup, you'll notice the address of the queue (line 3), the name of the queue (line 4) and the description of the queue that exists here (line 12-25). This pattern is true throughout the namespace - all entities are represented as an XML Entity Description wrapped in an Atom Entry.
Managing service bus entities is achieved by performing RESTful operations on these feeds within a service bus namespace over HTTPS: To create an entity we issue an HTTP PUT, to get an entity we issue an HTTP GET and to delete an entity we issue an HTTP DELETE. Enumeration is performed by issuing an HTTP GET within the reserved $Resources collection at the root of the namespace (for example, /$Resources/Queues).
Each type of entity and sub entity that you can create is represented in a hierarchy of Resource Descriptions. These include the familiar Queue, Topic and Subscription Descriptions and more advanced entities like Rule Description, Rule Filter and Rule Action:
The Resource Description types encapsulate the Content of an Atom entry that represents a service bus entity - when serialized to XML (using the DataContractSerializer) and wrapped in an Atom entry, these types can be used to create, delete, list and represent entities in service bus.
Within the Sample Service Bus Library for Windows 8, a Resource Description can be expressed as an Atom Entry by calling the AsSyndicationItem() method; the SyndicationItem type is within System.ServiceModel.Syndication namespace which provides classes to work with both RSS and ATOM feeds. Similarly, a Resource Description can be extracted from an Atom Entry by using the static ResourceDescription.Create<T>(SyndicationItem) method and specifying the expected resource type as the type parameter, T (for example, T could be QueueDescription).
Understanding how we model the descriptions of various service bus entities (as ResourceDescriptions) and how we convert those descriptions to and from Atom (using the ResourceDescription.AsSyndicationItem() and ResourceDescription.Create<T>(SyndicationItem item) methods) we're well prepared to see how the Create, Get, List and Delete operations are implemented. We'll use Queues to examine how management operations are implemented, but the logic for Topics, Subscriptions and Rules is extremely similar.
Let's take a look at creating a Queue:
Queue myQueue = await Queue.CreateAsync("Foo", tokenProvider);
When we call Queue.CreateAsync, we're going to perform the following operations:
You can visualize the Queue, NamespaceManager and SyndicationClient as each adding a layer of information to the original intent to create a queue called foo before handing the request off to service bus:
The Queue is a convenience class that encapsulates a Queue's description and also operations like Send/Receive in one place. The Queue type uses a NamespaceManager to Create, List, Get and Delete entities in a Service Bus namespace. The NamespaceManager is responsible for figuring out the full URI that an HTTP Request should be issued against (using the ServiceBusEnvironment) and wrapping Resource Descriptions in Atom (using the AsSyndicationItem method) before using a SyndicationClient to create HTTP Calls. The SyndicationClient is responsible for getting an authorization token (using a TokenProvider) and making HTTP calls (using HTTPClient).
All management operations happen the same way - they're first issued against a high-level abstraction like Queue, Topic or Subscription, passed down to a Namespace Manager for addressing and conversion to Atom then handled by a Syndication Client to perform the actual raw HTTP Request against service bus.
Runtime Operations: Send, Receive, Peek Lock, Abandon and Complete
Sending and receiving messages over HTTP is really simple. To send a message you issue an HTTP POST to the 'messages' collection of a Queue or Topic and to Receive (in receive and delete mode) you issue an HTTP DELETE to the head of the 'messages' collection of a Queue or Subscription. Peek locking is similarly achieved by issuing an HTTP POST to the head of the messages collection to create the peek lock; issuing an HTTP PUT to the lock location to abandon the message and issuing an HTTP DELETE to the lock location.
Service Bus Messages have Headers (like Sent Time, Message Id and Time-to-Live); user-specified message Properties and a body. Over HTTP, Headers are encapsulated as a JSON formatted structure in a reserved HTTP Header named BrokerProperties; user-specified message properties are encapsulated as plain HTTP Headers and the body of the service bus message is - you guessed it - the body of the HTTP Message. Sending a message to a queue is as simple as invoking SendAsync on that queue:
await myQueue.SendAsync("Hello, World!");
Let's take a look at a the HTTP trace for sending this message to get a better idea of what it looks like:
POST https://contoso.servicebus.windows.net/Foo/Messages HTTP/1.1
Host: contoso.servicebus.windows.net
Authorization: WRAP access_token="..."
Content-Type: text/plain
Content-Length: 13
Hello, World!
Receiving a message is similarly straightforward - this time we'll Receive and Delete from the head of the Queue:
BrokeredMessage message = await myQueue.ReceiveAndDeleteAsync();
And here's the corresponsing HTTP request and response traces:
DELETE https://contoso.servicebus.windows.net/Foo/Messages/Head?timeout=30 HTTP/1.1
Host: contoso.servicebus.windows.net
Authorization: WRAP access_token="..."
Content-Length: 0
-
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/plain
Server: Microsoft-HTTPAPI/2.0
BrokerProperties: {"DeliveryCount":1,"MessageId":"62a7eceab7eb4d52ac741af5f44393ce","SequenceNumber":1,"TimeToLive":922337203685.47754}
Date: Mon, 04 Aug 2015 16:23:42 GMT
Hello, World!
You can see here the simple format of a service bus message over HTTP and start to identify some of the metadata available in the BrokerProperties header. Within the Sample Service Bus Library for Windows 8, the type BrokeredMessage is used as an encapsulation for a service bus message, its headers, properties and body. Let's walk through how the call to SendAsync actually works:
The message sender also supports sending more complex types as the body of a message by serializing them to JSON. A MessageReceiver is used in a similar fashion to receive messages from a Queue or Subscription.
Hopefully this quick whirlwind-tour of the Sample Service Bus Library for Windows 8 gives you some pointers to get started. We're really excited to hear your feedback on the library and see the awesome connected apps you build with it - lets us know what you're up to on the discussion list for Windows Azure Toolkit for Windows 8.
Today, the Service Bus team is happy to announce a couple of initiatives to make it even easier to get started learning and using the Service Bus: the AppFabric Service Bus NuGet Package and the Service Bus Samples CodePlex Site. Both our Samples and SDK are still available as a download from MSDN, but we're hopeful that these new choices might be simpler and more convenient.
NuGet is an open source package manager for .Net which is integrated into Visual Studio and makes it simple to install and update libraries. While traditionally you would need to download an install an SDK before using it within your projects, NuGet adds a new 'Add Library Package Reference' option to Visual Studio which downloads, configures and updates the references you select automatically. The Service Bus NuGet Package contains two DLL files and configuration information needed to use the AppFabric May CTP - you can use this package instead of needing to download and install the Windows Azure AppFabric SDK v2.0 CTP May 2011 Update. Give it a try and let us know what you think in the AppFabric CTP Forums.
We're also excited today to offer you a new way to find and browse our library of sample code at our new CodePlex site. We'll be using the CodePlex site to help get more samples, tools and utilities out into your hands early and often. You can Browse the Source Code online or Download a copy if you prefer. Our CodePlex site licenses sample code to you under the open Apache 2.0 License - we're hopeful that makes it easier to re-use, re-distribute and share our sample code and tools. We'll be adding more code to the site regularly and would love to hear your feedback on the things you'd like to see us share.
As always, we're constantly hoping to hear from you about how we're doing - are CodePlex and NuGet useful delivery vehicles for you, or do you prefer to download and install the SDK and Samples? Please let us know on the forums!
The new Service Bus Durable Messaging features introduced with the May 2011 CTP are really cool, and what's even better than a slew of new messaging features added to the AppFabric is the fact that many of them are accessible from clients on any platform using HTTP. In this post, I'm going to introduce you to using the Service Bus REST endpoint for Messaging; some of it might remind you of the October CTP, we'll be using Queues (so taking a look at David's post from Tuesday could be a good idea), and getting to grips with How Access Control Tokens work over HTTP would be a great primer, too.
Typically, users of the Service Bus download and install the AppFabric SDK, add a reference to Microsoft.ServiceBus and/or Microsoft.ServiceBus.Messaging and use the ServiceBusNamespaceClient to perform management operations (creating, enumerating and deleting any queues, topics or subscriptions) or the MessagingFactory to Send and Receive messages. Details like addressing and security are taken care of by the SDK: there's no need to get or renew Access Control Service tokens and no need to interact directly with the service - you just use the SDK. With the REST endpoint, you get a little closer to the metal which - in this geek's humble opinion - can be at least a little bit more fun!
Wherever possible, you'll want to use our SDK. It sheilds you from some of the underlying complexity of the service, may help to protect you as features change in future and - frankly - it's just a lot easier. That said, there are plenty of times when you won't be able to use the SDK, for example: when working on a non desktop .Net Framework version (like Windows Phone 7 or Silverlight); when working on non-microsoft platforms (like iOS, Android, Java, PHP or Ruby); and when working with older versions of the .Net Framework.
For convenience and consistency, the code samples in this post are shown in C# - that's not because you'd be writing in C# when using the Service Bus from iOS, PHP or Ruby, of course! I want to focus today on showing some of the basics of using our REST API from a language that many of you will be familiar with. That said, you can look forward to future posts in a wider variety of languages showing the awesome things you can do with Service Bus across platforms and devices.
There are 5 things I'll be covering in this post to get you started - please leave your feedback on areas you'd like have more detail, examples and guidance either in the comments (below) or the AppFabric CTP Forums.
We're going to be busy - so make sure you have an account set up at the AppFabric Labs Portal and Lets Get Started!
Last Week, I provided some guidance on Getting and Understanding an Access Control Service Token via HTTP, so I won't provide a huge level of detail today on the topic. Suffice to say, the service bus requires that you present a WRAP access token in the HTTP Authorization Header, like this:
Authorization: WRAP access_token="<Your Token Here>"
Firstly, we'll get a token from ACS using the Issuer Name and Key which you can look up in the AppFabric Portal:
string serviceNamespace = "contoso"; string issuerName = "owner"; string issuerPassword = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa="; string acsBaseAddress = "https://" + serviceNamespace + "-sb.accesscontrol.appfabriclabs.com/"; // Note that the scheme is Http string relyingPartyAddress = "http://" + serviceNamespace + ".servicebus.appfabriclabs.com/"; // Create the body of the Post Request, formatted as a HTTP Form string postData = "wrap_scope=" + Uri.EscapeDataString(relyingPartyAddress) + "&wrap_name=" + Uri.EscapeDataString(issuerName) + "&wrap_password=" + Uri.EscapeDataString(issuerPassword); string authorizationToken; using (WebClient acsWebClient = new WebClient()) { // The response contains the access token and its expiry time formatted as an HTTP // Form like: wrap_access_token=<token>&wrap_expiry_time=2000 string response = acsWebClient.UploadString(acsAddress, "POST", postData); string[] tokenVariables = response.Split('&'); string[] tokenVariable = tokenVariables[0].Split('='); authorizationToken = Uri.UnescapeDataString(tokenVariable[1]); }
The access token contains its expiry time (currently defaulting to 20 minutes), and you can keep using the same token over-and-over again until it expires. However, once the expiry time elapses you'll need to request a fresh token from the Access Control Service. Now we'll go ahead and create a WebClient to use for our calls to the service bus; we initialize it by correctly setting the Authorization header - you need this header to be present in any call you make to the service bus.
WebClient webClient = new WebClient(); webClient.Headers["Authorization"] = "WRAP access_token=\"" + authorizationToken + "\"";
In the October CTP, we introduced the idea of Namespace Management: an explicit, RESTful interface to Create, Enumerate and Delete durable Service Bus entities (in the May CTP these are: Queues, Topics and Subscriptions). That concept carries through to the May CTP with just a couple of changes. You still use the established RESTful pattern (HTTP GET to retrieve/enumerate; HTTP PUT to create; HTTP DELETE to remove) to interact with Atom Feeds and Entries; we've simplified things by combining the Management Namespace (formerly https://<your-namespace>-mgmt.servicebus.appfabriclabs.com/) with the Service Namespace (still https://<your-namespace>.servicebus.appfabriclabs.com) though.
A queue can exist anywhere in your service namespace - you create it by putting the description of the queue to a 'vacant' uri in your namespace. We'll need to specify the correct content type for the request (Content-Type: application/atom+xml) then issue an HTTP PUT to the Uri of the new queue (using the secure, https scheme) containing the Atom Entry which defines it:
// Note that the scheme is Https string serviceAddress = "https://" + serviceNamespace + ".servicebus.appfabriclabs.com/"; string queueName = "MyFirstQueue"; string putData = @"<entry xmlns=""http://www.w3.org/2005/Atom""> <title type=""text"">" + queueName + @"</title> <content type=""application/xml""> <QueueDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"" /> </content> </entry>"; string queueAddress = serviceAddress + queueName; webClient.Headers["Content-Type"] = "application/atom+xml"; string response = webClient.UploadString(queueAddress, "PUT", putData);
The response to the request contains the Atom Entry for your newly created Queue (below) including all of the settable properties of the Queue Description. Updates to existing queues are not allowed, but you can include any of these properties in the Queue Description when you are creating a new queue.
<entry xmlns="http://www.w3.org/2005/Atom"> <id>https://willpe.servicebus.appfabriclabs.com/MyFirstQueue</id> <title type="text">MyFirstQueue</title> <published>2011-05-17T20:26:00Z</published> <updated>2011-05-17T20:26:00Z</updated> <author> <name>willpe</name> </author> <link rel="self" href="https://willpe.servicebus.appfabriclabs.com/MyFirstQueue"/> <content type="application/xml"> <QueueDescription xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <LockDuration>PT30S</LockDuration> <MaxQueueSizeInBytes>104857600</MaxQueueSizeInBytes> <RequiresDuplicateDetection>false</RequiresDuplicateDetection> <RequiresSession>false</RequiresSession> <DefaultMessageTimeToLive>P10675199DT2H48M5.4775807S</DefaultMessageTimeToLive> <DeadLetteringOnMessageExpiration>false</DeadLetteringOnMessageExpiration> <DuplicateDetectionHistoryTimeWindow>PT10M</DuplicateDetectionHistoryTimeWindow> </QueueDescription> </content> </entry>
Sending a message using the REST endpoint is really simple: just HTTP Post the body of the message to the Queue's incoming messages uri with the Authorization header in place (specifying the correct content type for the message's body):
string messageBody = "Hello World!"; string sendAddress = serviceAddress + queueName + "/Messages"; webClient.Headers["Content-Type"] = "text/plain"; webClient.UploadString(sendAddress, "POST", messageBody);
Messages can be received with either Peek Lock or Receive And Delete semantics; both are supported via REST, but for now we'll use Receive and Delete. Receiving in this mode is as simple as issuing a HTTP Delete request to the Head of the Message Queue with a receive timeout:
string receiveAddress = serviceAddress + queueName + "/Messages/Head?timeout=30"; string receivedMessageBody = webClient.UploadString(receiveAddress, "DELETE", string.Empty);
The receivedMessageBody contains the plain text sent earlier (neat!) - you can also take a look at the Response Headers to find more properties of the message:
X-MS-MESSAGE-ID: d78afc3299b54ab2bd0e97b183ab1f77 X-MS-DELIVERY-COUNT: 0 X-MS-SEQUENCE-NUMBER: 2 X-MS-SIZE: 12 Content-Type: text/plain
Finally, it's time to delete the queue; this is acheived by a simple HTTP Delete to the Queue's Address:
webClient.UploadString(queueAddress, "DELETE", string.Empty);
So, there we have it - a quick introduction to using the new REST features of AppFabric Service Bus Messaging. There's lots more you can do, and I'll be covering more of the features next week but it's never too early to send the team your feedback - visit the AppFabric CTP Forum and tell us what you think!
In particular, we'd love to hear from you around how you'll be using HTTP in Applications you build:
Take the HTTP Feature Survey to help shape the future of Service Bus!
Some people like to say that French is the language of love. Others - mainly those with more interest in slipping you a network stack than an afrodisiac - will tell you that HTTP is the protocol equivalent. The AppFabric Service Bus loves HTTP too, and it also loves Security: in this post, I'm going to show you how to get - and understand - a security token from the Access Control Service via HTTP.
Claims Based Auth 101To gain access to the service bus, you need to present a WRAP Access Token [PDF] in the HTTP Authorization Header for each of your calls. The content for that header is acquired from the access control service by presenting an assertion (like a signed Simple Web Token or a Username and Password pair) as a simple HTTP request; the response contains a set of claims (like who you are, where the token came from, how long the token lasts and which permissions the bearer has) which are signed to ensure authenticity.
Before we get started, you'll want to head over to the AppFabric Labs Portal. If you aren't signed up, take a moment to create a free account - once you're in click on the Service Bus node on the left and click the 'View' button on the right marked 'Default Issuer'. Note down the details (Issuer Name/Key) from here because you'll need them later.
Service Namespaces, Issers and KeysWhen you create a new Service Bus Namespace, a default identity is established in the namespace's associated Access Control Service namespace. This identity has both Shared Secret and Password credentials available - you can see those credentials by logging in to Access Control Management at https://[Your-Service-Namespace]-sb.accesscontrol.appfabriclabs.com/v2/mgmt/web/ServiceIdentity and clicking on 'owner' ('owner' is the name of the default service identity created when your account was provisioned). When your account is provisioned, the same key is used for both the Issuer Password credential and the Issuer Secret Key credential - this won't always be true as you create more issuers, passwords and secret keys: you don't need to have both a password and a secret key for an issuer, and if you do have both they don't need to be the same.
string serviceNamespace = "contoso"; string issuerName = "owner"; string issuerPassword = "<Enter Your Key Here>";
You can request a token from ACS using either the password or the shared secret - here is how they differ:
Regardless of how you request a token, you'll need to use the WRAPv0.9 ACS Endpoint for your Namespace (note the '-sb' suffix attached to the service namespace) and the Uri for your Service Bus service namespace using the HTTP:// scheme (even though, for security purposes, the service bus is only accessible over https, tokens must be requested for http).
string acsEndpoint = "https://" + serviceNamespace + "-sb.accesscontrol.appfabriclabs.com/WRAPv0.9/"; string relyingPartyAddress = "http://" + serviceNamespace + ".servicebus.appfabriclabs.com/";Method 1: Acquiring a Token with a Username and Password Getting a token using a username and password is really simple - just post a collection of values to the ACS Endpoint including the Relying Party Address ('wrap_scope'), the Issuer Name ('wrap_name') and the Issuer Password ('wrap_password'). The collection of response variables includes the token (but we'll get to that later!):
NameValueCollection postData = new NameValueCollection { { "wrap_scope", relyingPartyAddress }, { "wrap_name", issuerName }, { "wrap_password", issuerPassword }, }; WebClient webClient = new WebClient(); byte[] responseBuffer = webClient.UploadValues(acsEndpoint, "POST", postData); string response = Encoding.UTF8.GetString(responseBuffer);
Method 2: Acquiring a Token with a Shared Secret
The process with a Shared Secret is similar but has another step - we'll still post the Relying Party Address ('wrap_scope'), but instead of posting a username and password we'll send a Signed Simple Web Token ('wrap_assertion') along with a Token Format Identifier ('wrap_assertion_format', equal to 'SWT'). The token is simply a string containing the Issuer Name (in the format, Issuer={0}) signed with a HMACSHA256:byte[] issuerSecretBytes = Convert.FromBase64String(issuerSecret); string token = "Issuer=" + Uri.EscapeDataString(issuerName); string signature; using (HMACSHA256 sha256 = new HMACSHA256(issuerSecretBytes)) { byte[] signatureBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(token)); signature = Convert.ToBase64String(signatureBytes); } string signedToken = token + "&HMACSHA256=" + Uri.EscapeDataString(signature);
With the signed token computed, we construct a collection of post data and send it as before:
NameValueCollection postData = new NameValueCollection { { "wrap_scope", relyingPartyAddress }, { "wrap_assertion_format", "SWT"}, { "wrap_assertion", signedToken }, }; WebClient webClient = new WebClient(); byte[] responseBuffer = webClient.UploadValues(acsEndpoint, "POST", postData); string response = Encoding.UTF8.GetString(responseBuffer);
Now that we've seen how to get a token (in one of two excitingly similar ways) let's take a look at the response.
Understanding the TokenThe response is formatted as a Http Form (name1=value1&name2=value2) like this (the sensitive details have been scrubbed to protect the innocent):
wrap_access_token= net.windows.servicebus.action%3dListen%252cManage%252cSend%26http%253a%252f%252fschemas.microsoft.com%252faccesscontrolservice%252f2010%252f07%252fclaims%252fidentityprovider%3dhttps%253a%252f%252fwillpe-blog-sb.accesscontrol.appfabriclabs.com%252f%26Audience%3dhttp%253a%252f%252fwillpe-blog.servicebus.appfabriclabs.com%252f%26ExpiresOn%3d1305157180%26Issuer%3dhttps%253a%252f%252fwillpe-blog-sb.accesscontrol.appfabriclabs.com%252f%26HMACSHA256%3daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%253d &wrap_access_token_expires_in= 1199
The WRAP Access Token is the piece of this response that we need. It's Url Encoded (i.e. it can be decoded using Uri.UnescapeDataString):
net.windows.servicebus.action=Listen,Manage,Send &http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider=https://willpe-blog-sb.accesscontrol.appfabriclabs.com/ &Audience=http://willpe-blog.servicebus.appfabriclabs.com/ &ExpiresOn=1305157806 &Issuer=https://willpe-blog-sb.accesscontrol.appfabriclabs.com/ &HMACSHA256=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=
The token contains 5 claims and a signature:
In your application, you can use these values to figure out when to renew a token, how the user was authenticated and which actions the user is permitted to perform.
It might not be the sexiest of topics, but building, consuming, extending and debugging Test Frameworks is a large part of any SDET's day. Traditional wisdom teaches us to write abstraction layers - often many of them - to shield test cases from changes in the system under test: in API testing this often means creating scenario-focussed wrappers over the product; when testing UI this might mean adding layers of automation on top of the actual controls a user would interact with. We generally refer to these abstractions as Test Frameworks - they allow us to write test cases at a much higher level and reduce the maintenance burden of fixing test cases as a system under development inevitably changes.
Recently when struggling through a set of changes to one such framework, it struck me that we pour a lot of time and effort into these frameworks: would life be simpler, tests better and productivity higher without our obviously needed framework-friend? Maybe.
Firstly- we're building these frameworks to hide changes in the system under test. Aren't changes in the product exactly one of the things we'd like to be detecting? In simple tests and certainly tests of APIs, small changes which break tests might be pretty relevant for a feature tester to look at, but in higher-level, end-to-end scenarios, we're probably better off having these changes hidden. So, if our end-to-end, high level scenarios benefit from frameworks, what level of investment do we want to make in them? It probably depends on what portion of the test plan is comprised of end-to-end tests.
Another use of frameworks is to hide complexity in the product itself - consider an API where we need to instantiate an object, make a method call to initialize it, then execute an operation on it in order to achieve some customer scenario:
var iceCreamMachine = iceCreamTruck.CreateIceCreamMachine(Flavors.Chocolate); iceCreamMachine.TurnOn(); var treat = iceCreamMachine.MakeIceCream();Since spreading code like this all over our test cases is going to get messy, we add this Helper Method to the test framework:
T MakeTreat(IceCreamTruck truck, Flavors flavor) where T : Treat...It's great, it works and it makes our test code look a lot nicer. There's certainly no reason not to do this, but ask yourself this: If I want this helper method to make writing my code easier and cleaner, wouldn't my customers want it too?
We can add these abstractions and wrappers because we ignore or assume details: the system under test often allows a great deal of flexibility, often more than is required for the test cases in question. As the suite grows, more of the products 'knobs and levers' are altered by tests, meaning that more options creep into our wrappers too: sometimes this is a 'helper' class with more properties than the class it's helping you to use; sometime's its a 'helper' method with 15 oddly named parameters. Often - despite the best intentions of the framework's original designers - it becomes more complicated than the product it tests and is always less well documented.
I came to a basic conclusion: Test Frameworks are fun to write, but that doesn't always mean it's the right thing to do!
When dealing with the sordid topic of abstractions, it's worthwhile to remember a 1987 essay by Frederick P. Brooks Jr., No Silver Bullet, in which we're all reminded that "The complexity of software is an essential property, not an accidental one. Hence, descriptions of a software entity that abstract away its complexity often abstract away its essence." - translating this roughly into test parlance: Avoid abstracting away the thing you're trying to test.
In general development, any learned software engineer will tell you that readability of code is really important: for every time a line of code is written, it is read many, many times. Optimize for the time spent reading, not the time spent writing. In test, I'd like to propose something similar: for every time a test case is written, it will be read and maintained several times, but executed and investigated an order of magnitude more. Maybe we should start optimizing our tests for the times that they fail. After all, a test case is surely at its most useful when failing, since it is hinting at a defect in the product being tested. As soon as a test fails, I usually run through three steps of analysis:
Often, the exception actually thrown by the test case is fairly general - it's usually coming from somewhere deep in the test framework and doesn't give much clue to what's actually happened or what the expected outcome of the failing operation was supposed to be. Consider these two exception messages, this from a test framework:
The expected 'TastesIckyException' was not thrown.
... and this one from a test case:
Calling MakeIceCream with custom composite flavor 'Mango' and 'Bacon' should fail, because mixing sweet and savoury ice creams together is not allowed.
There's really not much difference between those two messages, but the second tells you a little more: the test was trying to use custom flavors; the test was using 'composite' flavors; the test was not expecting Mango and Bacon to be a valid flavor. You instantly have some idea about what the test is supposed to be doing and where the failure(s) might be.
In the first case, above, you'd need to dig into the framework to figure out what's going on - is the wrong overload of MakeIceCream() being called? Is the IceCreamMachine correctly configured with Mango and Bacon? Is it the right type of machine? Consider a second test case that looks like this:
var flavors = new CompositeFlavor(Flavors.Mango, Flavors.Bacon);
var iceCreamMachine = iceCreamTruck.CreateIceCreamMachine(flavors);
iceCreamMachine.TurnOn();
try
{
var treat = iceCreamMachine.MakeIceCream();
Fail("Calling MakeIceCream with the custom composite...")
}
catch (TastesIckyException e)
{
Log.Expected(e);
}
It's pretty obvious what's going on here, and has a nice side-effect. The test method describes the repro steps. A dev can read these and see:
Obviously, this is a fairly trivial - and specific - example. However, it's lead me to think about three things when writing new tests:
And lastly: it goes without saying that re-use isn't a bad thing, neither are common libraries or frameworks. We'll always benefit from common code, abstraction and toolkits - just consider how, where and why you're using them.
Last week at PDC we released a Community Technology Preview (CTP) of a new version of Windows Azure AppFabric Service Bus. You can download the SDK, Samples and Help on the Microsoft Download Center. There’s plenty new in this release and the first is the notion of Explicit Connection Point Management. In v1 whenever you started up a service and relayed it through the cloud over service bus we just quietly cooperated – this seems like a great idea until you think about a couple of advanced scenarios: Firstly: what happens when your service is offline but a sender (client) tries to connect to it? Well, we don’t know if the service is offline or the address is wrong (and there’s no way to differentiate); there’s no way to determine what’s a valid service connection point and what isn’t. There’s also no way to specify metadata about the service that connects (this is a HTTP endpoint, this endpoint is only Oneway). Also, you might have noticed that we added support for Anycast in v2 – how can you determine which connection points are Unicast (one listener/server and many senders/clients) and which are unicast (many load-balanced listeners and many clients)? That’s what connection points are for.
A Connection Point defines the metadata for a Service Bus connection. This includes the Shape (Duplex, RequestReply, Http or Oneway) and Maximum Number of Listeners and the Runtime Uri which acts as the service endpoint. Connection Points are managed as an Atom Feed using standard REST techniques. You’ll find the feed at the Connection Point Management Uri (-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints">https://<YourServiceNamespace>-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints)1 and it’ll look at little bit like this:
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">ConnectionPoints</title>
<subtitle type="text">This is the list of ConnectionPoints currently available</subtitle>
<id>https://willpe-blog-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints</id>
<updated>2010-11-01T20:53:53Z</updated>
<generator>Microsoft Windows Azure AppFabric - Service Bus</generator>
<link rel="self"
href="https://willpe-blog-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints"/>
<entry>
<id>https://willpe-blog-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints(TestConnectionPoint)</id>
<title type="text">TestConnectionPoint</title>
<published>2010-11-01T20:51:11Z</published>
<updated>2010-11-01T20:51:11Z</updated>
<link rel="self"
href="https://willpe-blog-mgmt.servicebus.appfabriclabs.com/Resources/ConnectionPoints(TestConnectionPoint)"/>
<link rel="alternate"
href="sb://willpe-blog.servicebus.appfabriclabs.com/services/testconnectionpoint"/>
<content type="application/xml">
<ConnectionPoint xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MaxListeners>2</MaxListeners>
<ChannelShape>RequestReply</ChannelShape>
</ConnectionPoint>
</content>
</entry>
</feed>
Writing some code to get your list of connection points is easy – in the rest of this post, I’ll show you how to (very simply) List, Create and Delete connection points. Before getting started, make sure that you’ve installed the October 2010 Windows Azure AppFabric SDK then create a new .Net Framework 4.0 (Full) Console Application in Visual Studio 2010.
Access to Service Bus Management is controlled by the Access Control Service. You’ll need to present the ‘net.windows.servicebus.action’ claim with a value ‘Manage’ in order to have permission to Create, Read and Delete connection points. The default issuer (owner) is configured to have this permission by default when you provision a new account.
We’ll need to go ahead and get a Simple Web Token from the Access Control Service for our request. Note that, by default, the realm (relying party address) used for service bus management has the http scheme: you must retrieve a token for the management service using a Uri with the default port and http scheme even though you will in fact connect to the service over https:
string authToken = GetAuthToken(new Uri("http://" + ManagementHostName + "/"));
Compile and run the app to see your current connection points (probably none). Now lets go ahead and create a Connection Point – to do this we just Post an Atom entry to the ConnectionPoint Management service. You can achieve this using classes from the System.ServiceModel.Syndication namespace3 but for clarity and simplicity we’ll stick to just using a big old block of xml encoded as a string – its not pretty this way, but it gets the job done!
var entry = @"<entry xmlns=""http://www.w3.org/2005/Atom"">
<id>uuid:04d8d317-511c-4946-bc1d-6f49b6f66385;id=3</id>
<title type=""text"">" + connectionPointName + @"</title>
<link rel=""alternate"" href=""" + endpointAddress + @""" />
<updated>2010-11-01T20:44:08Z</updated>
<content type=""application/xml"">
<ConnectionPoint xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns="""">
<MaxListeners>" + maxListeners + @"</MaxListeners>
<ChannelShape>" + channelShape + @"</ChannelShape>
</ConnectionPoint>
</content>
</entry>";
var request = HttpWebRequest.Create("https://" + ManagementHostName + "/Resources/ConnectionPoints") as HttpWebRequest;
request.Headers.Add(HttpRequestHeader.Authorization, "WRAP access_token=\"" + authToken + "\"");
request.ContentType = "application/atom+xml";
request.Method = "POST";
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(entry);
}
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
var connectionPoint = new StreamReader(responseStream).ReadToEnd();
Console.WriteLine(connectionPoint);
If you re-run your application now, you’ll see that you’ve created a connection point which is listed in the feed we retrieved earlier. The last thing to do now is clean up after ourselves by issuing a delete against the resource we just created:
using (WebClient client = new WebClient())
{
client.Headers.Add(HttpRequestHeader.Authorization, "WRAP access_token=\"" + authToken + "\"");
client.UploadString(connectionPointManagementAddress, "DELETE", string.Empty);
}
So, there we go: Listing, Creating and Deleting Connection Points. Download the full example from Skydrive:
___
1 You’ll need to have a WRAP token in the Http Authorization Header to access this resource, so you can’t just navigate to it in a browser.
2 Read more about the Access Control Service at Justin Smith’s blog. Sample code to retrieve a token is included in the download at the end of this post.
3 An example of using the Syndication primitives to manipulate connection points is available in the October 2010 Windows Azure AppFabric Sample ‘ManagementOperations’
Its just a few weeks ago that I started looking in more detail at the Windows Azure AppFabric Access Control Service (or just ACS to its friends) and one of the first things I wanted to figure out was how to federate between my on-premise Active Directory domain and ACS. With a few pointers, its not too tricky, but I figured I’d walk you through the whole process anyhow!
I’m going to assume that you’ve got an account set up with AppFabric Labs (http://portal.appfabric.labs.com) and an Active Directory domain installed too – if you don’t (or you want play about on a test domain) then just spin up a VM running Windows Server 2008 (or R2) and Install Active Directory Domain Services.
Here’s what we’ll do:
Download and Install ADFS v2
Create a Self-Signed SSL Certificate
Before you can configure ADFS you’ll need an SSL Certificate configured on your machine – if you have one already, skip ahead to the next step. Otherwise take you can setup a self-signed (untrusted) certificate using IIS. It goes without saying that you shouldn’t use a self-signed certificate in a production environment!
Configure ADFS and Enable Windows Authentication Endpoints
Establish a Trust relationship from ADFS to ACS
So, ADFS is now acting as an STS (Security Token Service) for your Active Directory domain, this means that you’re ready to setup federated authentication with other STSs or Identity Providers like the Windows Azure AppFabric Access Control Service (ACS). To do that, we need to establish a bidirectional trust relationship between ADFS and ACS – this allows your ACS project to process incoming tokens from your Active Directory and ensure that Active Directory trusts ACS and will issue tokens for use with it. We’ll be using AppFabric Labs for this – its free, so go Sign Up for an account if you don’t have one already.
Next, we need to perform a very similar process on your ADFS server, establishing a trust relationship back to ACS.
Establish a Trust relationship from ACS to ADFS
ADFS won’t issue tokens for use against the Access Control Service if it doesn’t trust it – we’ll need to configure a default signing certificate in ACS, generate some Federation Metadata and share that with our ADFS instance to finish off the establishment of this trust relationship.
When you’re done, leave the ‘Open the Edit Claim Rules dialog’ option checked – we’ll use this dialog to add some rules to this trust relationship allowing data to flow from Active Directory and into ACS. To get back to this dialog, right click on the Relying Party Trust for ACS and click ‘Edit Claim Rules’
At this point, some congratulations are in order: you’ve installed and configured ADFS, you’ve created and uploaded a certificate to allow signing of your ACS Federation Metadata, you’ve established a bi-directional trust relationship between ADFS and ACS and you’ve specified some claims which can be passed through to the Access Control Service. There’s just a little more work ahead of you before you can perform that first piece of federated, claims-based authentication.
We’re almost done. Now that we’ve established a claims processing rule (pass through the Windows Account Name) associated with our newly trusted identity provider (your Active Directory Federation Server) we can fire up Visual Studio and write some code. In this next section, we’ll get a SAML Token from ADFS and exchange it for a SWT token via the access control service. Once you’ve got the Simple Web Token (SWT) the Authentication World becomes Your Oyster – go and use it to auth against web services/sites or anything else!
Use the Windows Identity Foundation to get a SAML token from ADFS
There are a couple of things we need to do to get a token from ADFS. Firstly, we’ll need to validate that Self-Signed Certificate we created a while ago for securing SSL traffic to and from the ADFS server, secondly we’ll use the Windows Identity Foundation to request the token from an ADFS endpoint.
private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return sslPolicyErrors == SslPolicyErrors.None
|| string.Equals(certificate.Issuer, "CN=vm-willpe-adfs.willpe.sb", StringComparison.InvariantCultureIgnoreCase);
}
ServicePointManager.ServerCertificateValidationCallback += RemoteCertificateValidationCallback;
var stsUrl = "https://vm-willpe-adfs/adfs/services/trust/13/windowsmixed";
WSTrustChannelFactory trustChannelFactory =
new WSTrustChannelFactory(new WindowsWSTrustBinding(SecurityMode.TransportWithMessageCredential),
new EndpointAddress(new Uri(stsUrl)));
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
trustChannelFactory.Credentials.Windows.ClientCredential.Domain = "<<Your NetBios Domain Name Here >>;
trustChannelFactory.Credentials.Windows.ClientCredential.UserName = @"<<Your Domain Username Here>>";
trustChannelFactory.Credentials.Windows.ClientCredential.Password = @"<<Your Domain Password Here>>";
var acsUrl = "https://willpe-blog.accesscontrol.appfabriclabs.com/";
RequestSecurityToken rst =
new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue, WSTrust13Constants.KeyTypes.Bearer);
rst.AppliesTo = new EndpointAddress(acsUrl);
rst.TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11;
WSTrustChannel channel = (WSTrustChannel)trustChannelFactory.CreateChannel();
GenericXmlSecurityToken token = channel.Issue(rst) as GenericXmlSecurityToken;
string tokenString = token.TokenXml.OuterXml;
return tokenString;
private static string GetSamlToken(string domain, string userName, string password)
{
var acsUrl = "https://willpe-blog.accesscontrol.appfabriclabs.com/";
var stsUrl = "https://vm-willpe-adfs/adfs/services/trust/13/windowsmixed";
WSTrustChannelFactory trustChannelFactory =
new WSTrustChannelFactory(new WindowsWSTrustBinding(SecurityMode.TransportWithMessageCredential),
new EndpointAddress(new Uri(stsUrl)));
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
trustChannelFactory.Credentials.Windows.ClientCredential.Domain = domain;
trustChannelFactory.Credentials.Windows.ClientCredential.UserName = userName;
trustChannelFactory.Credentials.Windows.ClientCredential.Password = password;
try
{
RequestSecurityToken rst =
new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue, WSTrust13Constants.KeyTypes.Bearer);
rst.AppliesTo = new EndpointAddress(acsUrl);
rst.TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11;
WSTrustChannel channel = (WSTrustChannel)trustChannelFactory.CreateChannel();
GenericXmlSecurityToken token = channel.Issue(rst) as GenericXmlSecurityToken;
string tokenString = token.TokenXml.OuterXml;
return tokenString;
}
finally
{
trustChannelFactory.Close();
}
}
Add a line to the Main method to call GetSamlToken and verify that you get a nice, chunky XML token back from ADFS. With just a couple more lines of code, all of that markup will become a Simple Web Token.
Submit the SAML token to ACS to retrieve a set of claims as a SWT token
The hard work is over now – all we need to do is submit the SAML token we retrieved to ACS and get a Simple Web Token in response. With that token, you’re good to authenticate against any (properly configured) resource secured by the AppFabric Access Control Service.
NameValueCollection parameters = new NameValueCollection();
parameters.Add("wrap_scope", "https://willpe-blog.accesscontrol.appfabriclabs.com/mgmt");
parameters.Add("wrap_assertion_format", "SAML");
parameters.Add("wrap_assertion", samlToken);
private static string GetSwtToken(string samlToken)
{
var appliesTo = "https://willpe-blog.accesscontrol.appfabriclabs.com/mgmt";
var acsStsUrl = "https://willpe.accesscontrol.appfabriclabs.com/WRAPv0.9/";
try
{
WebClient client = new WebClient();
client.BaseAddress = acsStsUrl;
NameValueCollection parameters = new NameValueCollection();
parameters.Add("wrap_scope", appliesTo);
parameters.Add("wrap_assertion_format", "SAML");
parameters.Add("wrap_assertion", samlToken);
byte[] responseBytes = client.UploadValues("", parameters);
string response = Encoding.UTF8.GetString(responseBytes);
return Uri.UnescapeDataString(response
.Split('&')
.Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase))
.Split('=')[1]);
}
catch (WebException wex)
{
string value = new StreamReader(wex.Response.GetResponseStream()).ReadToEnd();
throw;
}
}
So, there we go – we’ve installed and configured ADFS, Created a Trust Relationship between the AppFabric Access Control Service and your new ADFS Instance, we configured ACS to accept incoming claims from the Active Directory Identity Provider and pass-through the Windows Account name. Then we used WIF to get swap our Windows Credentials for a SAML token which we sent to ACS to get a Simple Web Token. The result? A little string like this:
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname=WILLPE\Test
&http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider=http://VM-WILLPE-ADFS.willpe.sb/adfs/services/trust
&Audience=https://willpe-blog.accesscontrol.appfabriclabs.com/mgmt
&ExpiresOn=1288060895
&Issuer=https://willpe-blog.accesscontrol.appfabriclabs.com/
&HMACSHA256=[Base64-Hash-Code]
You can download the full sample from SkyDrive – feel free to leave any comments/questions below or find me on Twitter (@willpe)
I hope this helps,
Will
If you’re using the Windows Azure AppFabric Access Control Service (ACS) you’ve probably encountered a Simple Web Token (SWT) accessed via the Web Resource Authorization Protocol (WRAP). Doing this recently, I wanted to figure out when my token expired (so that I could cache it until a couple of minutes before expiry, improving my app's performance) – you might find this snippet useful if you want to figure out when a SWT token expires:
/// <summary>
/// Gets the UTC time that the specified token expires.
/// </summary>
/// <param name="token">An Access Token from the Access Control Service .</param>
/// <returns>The time that the token expires as a UTC DateTime.</returns>
public static DateTime GetExpiryTime(string token)
{
var swt = token.Substring("wrap_access_token=\"".Length, token.Length - ("wrap_access_token=\"".Length + 1));
var tokenValue = Uri.UnescapeDataString(swt);
var properties = (from prop in tokenValue.Split('&')
let pair = prop.Split(new[] { '=' }, 2)
select new { Name = pair[0], Value = pair[1] })
.ToDictionary(p => p.Name, p => p.Value);
var expiresOnUnixTicks = int.Parse(properties["ExpiresOn"]);
var epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
return epochStart.AddSeconds(expiresOnUnixTicks);
}
The code takes an access token from ACS (of the format wrap_access_token=”[Insert-SWT-Here]”) and extracts the ‘ExpiresOn’ value from the SWT. According to the OAuth WRAP Spec, this is a Unix time (i.e., the number of seconds past January 1, 1970 at 12am) expressed as a UTC time. So, don’t forget that if you want to figure out when the token expires in your local time zone, you’ll need to convert it using the TimeZone type:
Console.WriteLine("Your auth token expires at {0}.", TimeZone.CurrentTimeZone.ToLocalTime(this.AuthTokenExpiry));
I hope this helps,
Will
Iterators in C# are probably one of the least understood and most wonderful features the language has. They were added in C# 2.0 and are the magic that gives LINQ its Deferred Execution goodness. Anyway, I was needing an arbitrary length list of Guids today (although, with the recent shortage, perhaps ScottGuIDs would have been a better choice) and used this cute little few-liner to get what I wanted:
public IEnumerable<Guid> Guids
{
get
{
while (true)
{
yield return Guid.NewGuid();
}
}
}
From there you can easily get yourself a list of, say, 5 Guids using LINQ’s Take Extension Method:
Pretty terse, right?
For a few days this autumn (or is it Winter now?) I’ll be out and about talking to great uni students about Microsoft Codename ‘M’, and some of the fantastic technical opportunities for graduates at Microsoft. Here are some resources:
Apply for a Position at Microsoft
If you’d like to apply then use one of then send your CV/Resumé to us. Don’t forget to tell as about the things that really make you stand apart from your peers like your best university and individual projects or jobs!
Full Time: MSGradCV@microsoft.com
Intern: InternCV@microsoft.com
Codename ‘M’ Resources
- Video: A Lap Around Oslo
- Video: Oslo: The Language
- Video: Textual DSLs
- Video: Repository and Models
When using these resources, please remember that this is a really early preview. That means its all likely to change, its not ready for production and there are likely plenty of bugs! To help shape the future of modeling on our platform, please send your feedback using Connect!
Replay the London Event
I’ll be uploading the meeting recording from the London student partners event soon – please check back!
For now, you can grab the slide deck from skydrive.
If you’ve got any questions or comments, just post a comment, and I’ll get back to you asap!
Its been a fun and exciting week. Not only has Copenhagen managed to give us sunshine for days at a time, but I received my new tablet pc and home server too!
Tablet PCs are the coolest thing. Ever.
To help me to be a better ‘mobile worker’ (i.e. work on the train to work as well as at home and in the office) I’m given a laptop at work, since I already have a slew of big, chunky performance laptops under my belt, I thought I’d opt for something a little more exciting, like the HP 2710p Ultralight Notebook. Its light, gives a totally reasonable 4 hours of battery life under (what I consider) normal load and best of all, has that cool swiveling tablet functionality.
In case you’re not familiar with Tablet PCs, the screen rotates thru 180 degrees allowing you to close the laptop with the screen facing outwards, then use the stylus to write on it like a real, physical notebook. The most shocking thing is that it actually works! Its really easy to take notes on, the touch screen is responsive and crystal clear, coupled with OneNote and I haven’t used a piece of paper since the thing landed in my lap.
Windows Vista has some awesome built in tablet functionality, mainly the writing space overlay you are given to hand-write into any text box – the recognition is astounding, even my worst scrawled, scripted handwriting is correctly converted into typed characters. I’m experiencing an accuracy of about 95%, and its getting better every day, since windows is automatically adjusting to my style. Its weird, but I’ve really gotten used to having this new way to interact with my machine – from crossing out dodgy parts in Word document with a red felt tip, to circling mistakes in an excel graph and signing and mailing documents electronically, rather than the old Print-Sign-Fax farce of yesteryear.
The only mystery is why these things never took off… any ideas?
Windows Home Server
My old server didn’t quite make the trip to Copenhagen; I shouldn’t be surprised that it finally gave up living since in one form or another the poor thing has been alive (and abused) for close to 7 years now. Anywho, the upside of its sad demise is that the insurance company paid out for the cost of a similar replacement, and the payout stretched easily to buying myself a shiney new HP MediaSmart Server.
As you might expect, its cool. It looks great, makes pretty much no noise (although there is a fan, which you can just about hear when is deathly quiet, a situation which rarely occurs in my house) and works way better than I expected. Just stick the install CD into a machine, whack the next button until it isn’t there anymore and you’re done – its working, on the network, named sensibly and ready for your files/backups/photos/music/whatever. Of course, there was the small matter of installing Power Pack 1, but the download was tiny and the install was painless.
Its my first look at the Home Server OS – which looks like it’s been derived from Server 2003 – and it seems like a pretty sweet platform. Being able to remote desktop into it is a great feature, and taking the ‘You can break your server by doing this’ warnings with a pinch of salt it seems like its really versatile! I’ll need to get it working with my VOIP phones sometime this week by seeing how much it likes Axon – we’ll see how that goes, but for now, its two thumbs up.
SDET on Windows Azure Service Bus
SDET on Dynamics NAV
SDET Intern on Windows Workflow Foundation