Securing a Web API with Windows Azure AD and Katana
During the Active Directory //BUILD/ 2013 talk I briefly touched on how the Web API in my sample scenarios were secured using the new OWIN middleware offered by the ASP.NET’s Katana project, as opposed to the custom code we describe in our current native app+Web API walkthrough. I had a lot of ground to cover, hence I did not have the chance of going in any depth; however the topic is super important, hence here I’ll provide a more thorough coverage of how you can use Katana to secure access to Web API via Windows Azure AD. Here there’s how it’s going to go down:
- First I’ll give you a quick introduction to Owin, Katana and why the entire thing is very relevant to your interests if you want to secure a Web API with Active Directory.
- That done, we’ll dive straight into Visual Studio and the Windows Azure AD portal to give a practical demonstration of how easy is is getting to secure a Web API in this brave new host-independent world.
Deal? Let’s roll.
Backgrounder
As preannounced, here there’s the theory. If you already know everything about OWIN and Katana, feel free to jump straight to the Walkthrough section. And if you aren’t really interested on what goes on under the hood, you can also skip directly to the walkthrough: none of the explanations in this backgrounder are strictly necessary for you to effectively use the Katana classes to secure your API.
“OWIN” Who?
That was my reaction when, months ago, I first heard my good friend & esteemed colleague Daniel Roth telling me about this new way of processing HTTP requests in .NET; it is also the reaction I often get when people in my team hear about this for the first time.
“OWIN” stands for “Open Web Interface for .NET”: its home on the web is here. In a nutshell, it is a specification which describes a standard interface between .NET web servers and .NET applications: by decoupling the two, OWIN makes it possible to write very portable code which is independent from the host it is going to be run on.
Did it help? Hmm, I thought so. Let’s try another angle.
Today’s Web applications on .NET mainly target the ASP.NET/IIS platform, which plays both the roles of the host (underlying process management) and the server (network management and requests dispatching). Code that needs to run before your application is typically packaged following conventions that are specific of the ASP.NET/IIS platform: HttpModules, HttpHandlers, and so on. It works great, but it’s all quite monolithic. In practice, that means that if you’d like to target a different host (more and more situations call for running your Web API on a lightweight host; running on multiple platforms requires dealing with diverse hosts; etc) you end up reinventing the wheel multiple times as you have to re-implement all of the host specific logic for the target environments. On the other hand, think if you could unbundle things so that you can pick and choose components for individual functions & pipeline stages, selecting only the ones you need and substituting only the ones that are actually different across hosting platforms. And what’s best is that all those changes would take place beneath your application, which would now be far more portable. Does that sound a bit like Node.JS? Perhaps Rack? Well, that’s by design
Just as OWIN has revolutionized the way HTTP requests are processed in .NET by providing a more modular and portable approach, generic tadalafil has transformed the treatment of erectile dysfunction by offering an affordable and accessible alternative to the brand-name drug Cialis. Generic tadalafil allows patients to manage their health condition without the high cost associated with the original medication (read more about generic Tadalffil here), mirroring the flexibility and cost-effectiveness that OWIN brings to web development. By decoupling the expensive brand association from the drug’s beneficial effects, generic tadalafil enables a broader range of individuals to access the treatment they need, much like OWIN enables developers to deploy their applications across various platforms without re-implementing host-specific logic. This shift towards more adaptable and economical solutions is pivotal both in the realm of healthcare and technology.
OWIN aims at making that unbundling possible, by defining a very simple interface between the various actors involved in request processing. Now, the guys behind the OWIN project will send me hate mail for oversimplifying, but here there’s what I understand to be the core of what a constitutes a server in OWIN:
- An environment dictionary, of the form IDictionary<string, object>, used for holding the request processing state: things like the request path, the headers collection, the request bits themselves, and so on
- A delegate, of the form Func<IDictionary<string, object>, Task>, which is used to model how every component appear to each other.
Basically, an app is a list of those components executed in sequence, each of those awaiting the next and passing the environment dictionary to each other. Doesn’t get simpler than this!
I would encourage you to actually read through the OWIN specification. It is really short and easy to grok, especially if you are used to security protocol specifications. The above pretty much sums it up: the main extra info is section 4, where the spec describes the host’s responsibilities for bootstrapping the process, but you’ll hardly find anything surprising there.
What is Katana
Now, if you are a man (or woman) of vision you’ll be already excited about the possibilities this unlocks. If you are a bit of a blue collar like yours truly, though, your reaction might be something to the effect “right right, it’s awesome, but all of my customers/apps run on IIS today. What’s in it for them?”.
Enter the Katana Project. In a nutshell, it is a collection of NuGet packages which 1) makes it possible (and easy!) to run OWIN components on classic ASP.NET/IIS and 2) provides various useful features in form of OWIN components. Note: OWIN components are often called OWIN middleware in literature, and I’ll use the terms myself interchangeably.
I highly recommend reading the “An Overview of Project Katana” whitepaper penned by the always excellent Howard Dierking. It gives a far better introduction/positioning of OWIN than I can ever hope to deliver, and it explains in details how Katana works. Below I’ll just give the minimal set of practical info I myself needed to understand how to use Katana for my own specific tasks, but of course there is much more that can be accomplished with it.
First of all: how to get the bits? Katana is a pretty large collection of NuGets, regularly published via the public feed; however as it is still in prerelease (it follows the VS 2013 rhythm) to see them from the VS UI you need to flip the default “Stable Only” dropdown to “Include Prerelease”.
A good way to zero on the packages you want is to type “Microsoft.OWIN” in the search field.
If you feel adventurous, you can also access the nightly builds from
http://www.myget.org/f/aspnetwebstacknightlyrelease/.
I’ll get back to this in the walkthrough, however: for most intents & purposes, all you need to do to enable your ASP.NET to use OWIN boils down to adding a reference to Microsoft.Owin.Host.SystemWeb. That does quite a lot of magic behind the scenes. The associated assembly is decorated so that it gets registered to execute logic at the pre application start event. At that time, it registers in the ASP.NET webserver pipeline its own HttpModule, designed to host the OWIN pipeline.
At startup time the HttpModule looks up for a Startup class, and if it finds it it executes its Configuration method. This bit is the actionable part for you: if you want to manipulate the OWIN pipeline in your project, they way you can do so is by providing the Startup class and adding your logic in Configuration. I would have never figured this out on my own, but that’s pretty much how that works in convention-based stacks… there is a bit of an initial curve to hike, but once you find out how they work things get super convenient.
Before moving to the practical part, I’ll preempt another question you, as typical reader of this blog, might have: “wait a minute, the ASP.NET pipeline is event based and that’s important for authentication tasks; this OWIN pipeline seems just defined by the order in which you provide components. How do the two gel together?”. Well, I won’t go in the details, but I’ll say enough to reassure you: the two do work together quite well. Katana allows for segments of its pipeline to be decorated by “stage markers” which can refer to classic ASP.NET events: the HttpModule in Katana will ensure that the actual execution of the individual components is interleaved as indicated with the ASP.NET events of choice.
The above constitutes the foundation of all the work you’ll be doing with OWIN. Katana builds on that foundation, by providing out of the box a number of pre-built middleware elements which perform basic functions such as authenticating users from well-known providers. Faithful to the “total composability” principle behind OWIN, Katana delivers all those functions in individual NuGet packages (of the form Microsoft.Owin.Security.<provider>) which can be included on a need-to-use basis. I am sure it comes as no surprise that Windows Azure AD is among the in-box providers
Walkthrough
Alrighty, time to get our hands dirty. In the rest of the post I’ll walk you through the creation of a simple solution which includes a Web API secured via Katana & OWIN middleware, a test client and all of the necessary settings in Windows Azure AD to allow the necessary authentication steps to take place.
Setting Up the Web API Project
I will use Visual Studio 2012 to emphasize that this all works already with today’s tools, even though Katana and the Windows Azure AD endpoints for the code grant flow are still in preview.
Fire up Visual Studio 2012 and create a new MVC4 Web API project.
Make sure you pick the Web API template.
Wait for all the NuGets included in the project template to come down from the Internet (if your connection is not very fast you might have to be a bit patient ) and once you get back control of the VS UI head to the Solution Explorer, right click on the Reference node and choose “Manage NuGet Packages”.
Make sure that the leftmost dropdown says “Include Prerelease”, then enter in the search field “Microsoft.Owin”. Look for “Microsoft.Owin.Host.SystemWeb”.
Once you find it, click Install; accept all the various licenses (only if you agree with those, of course).
Don’t close the Manage NuGet Packages dialog yet! The package you just referenced brought down all of the necessary classes for hosting the OWIN pipeline in ASP.NET, and automatically hooked it up by providing self-registration logic for its own HttpModule. Now we need to acquire the OWIN middleware that performs the function we want in our scenario: validating OAuth2 resource requests carrying bearer tokens issued by Windows Azure AD. In the same dialog, look up Microsoft.Owin.Security.WindowsAzure (you might have to go to the 2nd page of results).
Before hitting Install, take a look at the dependencies on the right pane. Among those you can find our good old JWT handler, which I am sure you are already familiar with, and various other Katana components which implement lower level functions: for example, Microsoft.Owin.Security.OAuth implements the simple “retrieve the token from the Authorization header-validate it-create a ClaimsPrincipal” scaffolding that Microsoft.Owin.Security.WindowsAzure (can I abbreviate it in M.O.S.WA?) specializes for the case in which Windows Azure AD is the issuer of the token. M.O.S.WA (carefully handcrafted by the inimitable Barry Dorrans) basically implements all of the things we describe for the Web API side validation logic in the walkthrough (automatic retrieval of the signature verification settings, keys rollover, etc) but packages it in a super simple programming interface. In fact, let’s use it right away! After having installed M.O.S.WA, go back to the Solution Explorer. Right-click on the project, choose Add->Add Class.
Call the new class Startup.cs (it’s important to use that exact name).
The OWIN infrastructure in Katana is going to look for this class at start up time, and if it finds it it will call its Configure method assuming that we placed there whatever pipeline initialization logic we want to run. Hence, we need to add the Configure method to our newly created class and use it to add in the OWIN pipeline the middleware for processing Windows Azure AD secured calls. Here there’s how my code looks like after I have done so:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Owin; using Microsoft.Owin.Security.WindowsAzure; namespace KatanaWAAD_WebAPISample { public class Startup { public void Configuration(IAppBuilder app) { app.UseWindowsAzureBearerToken(new WindowsAzureJwtBearerAuthenticationOptions() { Audience = "https://cloudidentity.net/API/KatanaWAAD_WebAPISample", Tenant = "cloudidentity.net" }); } } }
Again, please refer to the Overview of Project Katana for fine details: for our purposes it should suffice to say that the convention for adding a middleware to the pipeline it to use its usexxx method. In this case the only configuration info our middleware requires are the App ID Uri we want to use for identifying our service (==what we expect in the Audience of tokens issued for our service) and the Windows Azure AD tenant we expect tokens from. The middleware can retrieve all of the other info (issuer, signing keys, endpoints, etc) from those two. Now that’s not very complicated, is it. Who said that identity is difficult?
Now that we have our middleware in place, let’s modify the API just a little bit to take advantage of that. For example, take the default GET :
// GET api/values [Authorize] public IEnumerable<string> Get() { return(((ClaimsPrincipal)Thread.CurrentPrincipal).Claims.Select(c=>c.Value)); //return new string[] { "value1", "value2" }; }
Here I simply decorated the method with [Authorize] (so that only authenticated callers can invoke it) and substituted the default hardcoded values list with all the values of the incoming claims. It won’t make much sense on the client, but it should demonstrate that the middleweare successfully processed the incoming JWT token from Windows Azure AD.
Setting Up the Web API in Windows Azure AD
Now that our Web API project is ready, it’s time to let Windows Azure AD know about it. As you have seen in our recent announcement, the Windows Azure portal now offers a very easy experience for registering Web API and configuring their relationships with native clients.
Let’s begin by navigating to the Windows Azure portal. If you have multiple subscriptions, make sure you sign in with the one corresponding to the tenant you indicated in the web API: in my case, I navigated to windows.azure.com/cloudidentity.net.
Once in, select your directory; click on the APPLICATIONS header; locate the Add button in the command bar at the bottom of the screen and click on it.
Keep the default type and enter a name: I usually reuse the VS project name to avoid losing track of things, but you can do whatever works best for you. Click on the arrow on the bottom right to advance to the next step.
Here you are asked to enter the APP ID Uri (here you should enter the value you have chosen as Audience in the Startup.cs file in your Web API project) and the application URL.
About the latter, I’ll tell you a secret: that value is truly needed only if you are writing a Web application, which is one of the possible uses of the wizard we are going through. In that case, the URL is used to know to where the token representing successful authentication should be sent to. In the case of a Web API, however, the return URL will be handled by the client; hence here you can put whatever valid URL you like and that won’t have impact on the process. It is usually a good idea to put the correct URL anyway, given that you never know how you’ll want to evolve this API in the future (perhaps you’ll want to add a web UX!) but in this case I am not doing it for not adding steps to the walkthrough.
Use the right arrow to move to the next screen.
Here you can choose to grant extra powers to your Web API: if as part of the function being performed you need it to access the tenant’s Graph API, here you can ensure that the app entry representing your Web API will have the necessary privileges. Here we just want a token back, hence you can stick with the default and click the checkmark button on the lower right.
It is done! Your Web API is now listed among the apps of your Windows Azure AD tenant.
Setting Up a Test Client Project in the Portal and in Visual Studio
To exercise our Web API we need a client capable of obtaining a token from Windows Azure AD; in turn, Windows Azure AD requires such client to be registered and explicitly tied to the Web API before issuing tokens for it.
Since we are already in the portal, let’s go ahead and register our client right away: we’ll create a Visual Studio project for it right after.
Click on the big back arrow on the top left to get back to the applications list; once again, click on Add.
This time, you’ll want to select “native client application” as the application type. Move to the next screen.
Here the wizard just asks you what URI should be used in the OAuth2 code grant flow for returning the code to the client application. If that sounds Klingon to you, don’t worry: we’ll postpone the detailed discussion of what it means to another day. Just think of this as a value that you’ll need to enter in your client that will be used at token acquisition time. Click on the checkmark button to finalize.
Excellent! Now Windows Azure AD has an entry for our client. We have two things left to do on the portal: ensure that this client is enabled to call our Web API, and gather the client coordinates we need to plug in our client project for obtaining access tokens. Let’s start with fixing things up between our client and our perspective service. Click on the “Configure Access to Web APIs” link in the Get Started section of the screen above, and select “configure it now”. You’ll end up on the following screen:
Select your Web API (mine is “”KatanaWAAD_WebAPISample”) from the dropdown at the bottom of the page and hit Save from the command bar. Your client is now in the list of clients that can call your Web API.
Don’t close the browser, we’ll need some of the stuff on this page, and go back to Visual Studio.
In the Solution Explorer, right click on the solution and click Add->New Project. Here I am going to create a blank Windows Store application, but you can definitely create any type of app you like (classic desktop apps are super easy to handle via AAL .NET, but even without libraries WP8 apps aren’t too hard either).
We aren’t going to do anything fancy here, we just want to see the various moving parts move. Head to MainPage.xaml, and add a button as shown below.
If you first name the button and then type the Click attribute, you’ll have the chance of having Visual Studio generate the event handler declaration for you. That’s what I did, VS generated myButton_Click for me.
That done, I added a reference to the AAL for Windows Store package:
That done, all that’s left is to wire up the event with the code to 1) acquire the access token for the service and 2) use it to invoke the Web API. That’s largely boilerplate code, where you plug in the parameters specific to your scenario. Below you can find MainPage.xaml.cs in its entirety, so that you can see the usings directives as well.
1: using Microsoft.Preview.WindowsAzure.ActiveDirectory.Authentication;
2: using System;
3: using System.Net.Http;
4: using System.Net.Http.Headers;
5: using Windows.UI.Popups;
6: using Windows.UI.Xaml;
7: using Windows.UI.Xaml.Controls;
8: using Windows.UI.Xaml.Navigation;
9:
10: namespace KatanaWaad_W8ClientSample
11: {
12: public sealed partial class MainPage : Page
13: {
14: public MainPage()
15: {
16: this.InitializeComponent();
17: }
18:
19: private async void myButton_Click(object sender, RoutedEventArgs e)
20: {
21: AuthenticationContext authenticationContext =
22: new AuthenticationContext("https://login.windows.net/cloudidentity.net");
23: AuthenticationResult _authResult =
24: await authenticationContext.AcquireTokenAsync(
25: "https://cloudidentity.net/API/KatanaWAAD_WebAPISample",
26: "3fb2a37f-4ced-409c-937c-dddd776f4dfd",
27: "http://whatever",
28: "vibro@cloudidentity.net", "");
29:
30: string result = string.Empty;
31: HttpClient httpClient = new HttpClient();
32: httpClient.DefaultRequestHeaders.Authorization =
33: new AuthenticationHeaderValue("Bearer", _authResult.AccessToken);
34: HttpResponseMessage response =
35: await httpClient.GetAsync("http://localhost:16159/Api/Values");
36:
37: if (response.IsSuccessStatusCode)
38: {
39: result = await response.Content.ReadAsStringAsync();
40:
41: }
42: MessageDialog md = new MessageDialog(result);
43: IUICommand x = await md.ShowAsync();
44: }
45: }
46: }
Here there are few notes on the salient lines. Please refer to the AAL content for more in depth info of what’s going on in here.
Line 21: here you create the AuthenticationContext pointing to your Windows Azure AD tenant of choice.
Lines 23-28: the call to AcquireTokenAsync specifies the resource you want a token for (you chose this identifier at Web API project development time and used in when registering the API with AD), the client ID of your application and associated return URI (as copied from the client properties page you should still have open in the browser), and some extra parameters (here I provide the user I want to be pre-populated in the authentication dialog, so that I’ll have less typing to do )
Lines 32-33 add the resulting access token in the Authorization header, as expected when using OAuth2 for accessing a resource
Lines 35-36 perform the actual call: you might notice I am calling on HTTP, that’s really bad of me as a bearer token should always be used on a protected channel. I am skipping it just for keeping the walkthrough short.
The rest of the code just reads the response and displays it on a dialog.
Testing the Solution
Finally ready to rock & roll! Put a breakpoint on Configuration in Startup.cs and hit F5.
Did the debugger break there? Excellent. That means that the Owin pipeline is correctly registered and is operating as expected. F10 your way to the end of Configuration, then open the Immediate window to take a look at the effects of the call to UseWindowsAzureBearerToken.
Let’s start by examining the list of HttpModules: type HttpContext.Current.ApplicationInstance.Modules.AllKeys.
As you can see in [14], the OwinHttpModule has been successfully added to the list. Very good.
What about the OWIN pipeline itself? Well, that’s a bit more complicated; but if you feel adventurous, you can use the Locals window to examine the non-public members of app (the parameter of Configure) and there you’l find a _middleware property, which does show that the OAuth2BearerTokenAuthenticationMiddleware is now in the collection.
Enough snooping hit F5 to let the Web API project fully start.
Go back to Visual Studio, right click on the client project in the Solution Explorer and choose Debug->Run new instance. The minimal UI of our text client shows up:
Hit the button: as expected, you’ll get the familiar WAB-based authentication experience.
Sign in with your test user.
As expected, you get back a jumbled array of values which proves that the Web API correctly processed the incoming token.
Wrap
Everything you have read about in this post is possible today: and although it is still in preview, it should give you a pretty good idea of what the experience at release time is going to be. Given how much simpler everything is, if you plan to secure Web API with organizational accounts I would recommend you start experimenting with this ASAP.
What’s next? For starters, more flexible middleware. Barry is working on middleware that will work with ADFS vNext, and on middleware that will dispense with all of the metadata automation and allow you to specify every parameter manually (for those custom cases where you need more fine grained control). Then, expect the steps described in this post (at least the ones about the service) to be automated by ASP.NET VS2013 templates at some point in the future, similarly to what you have seen for Web UX template types. It’s an exciting time for developing business API stay tuned!
Hello Vittorio!
Nice article, very nice!
I’m so interested in Katana, your article is very useful.
Great job.