November 2013
Volume 28 Number 11
ASP.NET Web API - Secure ASP.NET Web API with Windows Azure AD and Microsoft OWIN Components
By Vittorio Bertocci | November 2013
As the role of the Web API becomes more prominent, so does the need to ensure you can use it confidently in high-value scenarios, where sensitive data and operations might be exposed.
The industry is clearly converging on a solution for securing REST APIs that relies on the OAuth 2.0 standard. In practice, though, this doesn’t offer detailed guidance on what should be done at the project level. Furthermore, the existing classes and tools in the Microsoft .NET Framework for securing communications were designed to work with particular application types (postback-based Web UX apps). They aren’t a good fit for Web APIs and the multi-client scenarios they enable. As a result, securing a Web API has been a fairly artisanal activity. It isn’t necessarily insecure, but varies greatly across solutions and requires far too much custom code.
With the release of Visual Studio 2013, you can leave all that behind. This edition introduces innovative ASP.NET tooling and security middleware from the Microsoft Open Web Interface for .NET (OWIN) components that make protecting your Web API straightforward. The new ASP.NET tools and templates let you configure a Web API project to outsource authentication to Windows Azure Active Directory (AD) directly, emitting the necessary code in the local project and in the corresponding entries in Windows Azure AD.
In this article, I’ll show you how to take advantage of these new Visual Studio 2013 features to create a simple Web API protected by Windows Azure AD. I’ll also show you how to create a test client so you can see the API in action. I’ll also take a quick look at what happens behind the scenes, which can serve as a starting point if you want to dig deeper and explore more advanced aspects of this scenario.
Authentication boils down to asking a caller, when sending a message to a server, to include some kind of credential that can verify his identity or retrieve his attributes. The server then uses that information for authorization—determining whether access should be granted and in what terms.
Resources often offload most of the authentication functions to an external services provider, commonly known as an authority or an identity provider. These providers take care of heavy-duty tasks such as onboarding users, assigning credentials, handling lifecycle flows (such as password recovery), providing a UI for user authentication, credential verification over multiple protocols, multiple authentication factor management, fraud detection and more.
With those functions out of the way, the only authentication task left is to verify that authentication succeeded at the authority of choice. This typically involves examining a security token, a data fragment issued by an authority to a caller upon successful authentication.
Security tokens are usually crafted according to a specific format, digitally signed by a key that will unequivocally identify the issuing authority, and contain some data that uniquely ties the token to the target resource. When the resource receives a request, it looks for an accompanying token. If it finds one that meets the required validation attributes, the caller is authenticated.
At that level of detail, the pattern is so generic it can describe many different approaches to authentication. I’ll apply it to this scenario by assigning the high-level roles to concrete entities.
The Resource The resource will be the ASP.NET Web API 2 project I need to secure. You can apply authentication requirements with finer granularity. For example, you can define a subset of actions to secure and leave others to accept anonymous callers.
The Authority I’ll configure the Web API to offload its authentication needs to Windows Azure AD, a Platform as a Service (PaaS) available to every Windows Azure subscriber. Windows Azure AD is specifically designed to support cloud-based application workloads. The service stores information about users (attributes and credentials) and organizational structure. You can synchronize its data with your Windows Server Active Directory, if you so choose, or live exclusively in the cloud with no need for an on-premises infrastructure.
Nearly every online Microsoft service (Office 365, Intune and Windows Azure) takes advantage of Windows Azure AD for its authentication and directory needs. Thanks to open standards and support for common protocols, you can connect to Windows Azure AD from virtually any application (Web UX, Web API, native client, server to server, and so on) and platform. I’ll demonstrate how to register your apps in Windows Azure AD and take advantage of its OAuth 2.0 endpoints.
Token Format and Validation The OAuth 2.0 specification doesn’t mandate any particular token format, but the JSON Web Token (JWT) format (bit.ly/14EhlE8) for REST scenarios has become the de facto standard. Both Windows Azure AD and the Microsoft OWIN components support the JWT format in OAuth 2.0 flows. I mention this mostly to provide some context. The mechanics of JWT acquisition and validation are all taken care of by the middleware, and the token format is transparent to the application code.
The Client When a resource relies on an authority to handle authentication, it’s effectively decoupled from the client. How the user (and the client application) obtains a token becomes a matter between the user and the authority. That’s great for code maintainability, but if you want to see your API in action, you still need to set up a client. You’ll learn how to register a native client for the Web API in Windows Azure AD, and how to use the Windows Azure AD Authentication Library (ADAL) to enable a .NET rich client application to authenticate users against Windows Azure AD and obtain tokens to secure calls to the Web API.
Figure 1 shows the various elements of the solution I’m going to build. Don’t worry if you don’t understand some of the labels at this point: Everything will be introduced as I walk through the development of the solution.
Figure 1 The Architecture of the End-to-End Solution
To create the Web API project, use the new ASP.NET tools and templates in Visual Studio 2013. Open Visual Studio and create a new ASP.NET Web Application project. In the new project dialog, select the Web API template. Click on the Change Authentication button.
You’ll be presented with the authentication styles you can choose out of the box for a Web API, as shown in Figure 2. Choose Organizational Accounts, which lets you use Windows Azure AD as the authority. (For more information on all of the options, see bit.ly/1bhWngl.) The goal here is to gather information about the characteristics of your Web API that are important from an identity management perspective, and to determine which Windows Azure AD instance (commonly known as a “tenant”) you should configure to handle authentication.
Figure 2 The Organizational Accounts Authentication Dialog
The first dropdown determines whether just one Windows Azure AD tenant (typical of a line-of-business application) or multiple Windows Azure AD tenants (as you’d expect from a Software as a Service [SaaS] application) should use the application. You’d normally select Single Organization if your app will be used by the employees in your company, or Multiple Organizations if the app will be accessed by users from many companies. That said, those two alternatives are currently available only for ASP.NET WebForms and ASP.NET MVC apps. Currently, the Web API project template supports only the Single Organization option.
The Domain textbox identifies which Windows Azure AD tenant should register your application. It’s typically the enterprise directory associated with your Windows Azure subscription, but any directory for which you have administrative credentials will do (more on that later). At creation time, every Windows Azure AD tenant has one, associated three-level domain in the form yourorganization.onmicrosoft.com. Generally, you’ll associate the tenant to one or more domains you already own. In the example in Figure 2, I use my own domain, cloudidentity.net.
The Access Level dropdown specifies which access rights the application should have against the directory. The default value, Single Sign On, lets the directory issue tokens for your application. This is a simple acknowledgement that the app is registered. The authority won’t issue tokens for unregistered apps, even upon successful authentication.
Other access levels include “Read directory data” and “Read and write directory data,” which respectively enable the application to query the directory and modify its content. It does this via the Graph API, a REST-based programmatic interface designed to let apps from any platform with an HTTP stack gain delegated access to the directory. I’ll stay with the default Single Sign On access level and not demonstrate the Graph in the Web API project. That is, however, an extremely powerful feature of Windows Azure AD. For more information on the Windows Azure AD Graph API, see bit.ly/1aByRLS.
After you enter the domain associated to your Windows Azure AD tenant, click OK to generate the project. The tool will perform two tasks:
- It will reach out to the selected Windows Azure AD tenant and add an entry describing the application being created.
- It will emit code for a Web API project, add the necessary security middleware from the Microsoft OWIN components to handle Windows Azure AD authentication and generate the necessary initialization code to validate incoming tokens according to the Windows Azure AD tenant of choice.
The first task is performed via the Graph API (Visual Studio is itself a client of the Graph API). In order to add the entry describing the application you’re creating to the directory, it needs to obtain a token from the directory proving you have the necessary privileges to write in the directory. That’s why, once you click OK, Visual Studio presents you with the authentication prompt you see in Figure 3.
Figure 3 Account Sign in Authentication Prompt
All you need to do is enter administrator credentials for the directory. The tool verifies you have the necessary privileges to perform the operations required. When you click OK, Visual Studio contacts Windows Azure AD and creates the project files.
You now have a fully configured Web API, ready to enforce that only callers from the specified Windows Azure AD tenant gain access. Let’s take a closer look.
Go to the Solution Explorer pane where you’ll see in the root a file called Startup.cs. If you read Howard Dierking’s “Getting Started with the Katana Project” from last month’s issue (msdn.microsoft.com/magazine/dn451439), you already know the class in this file is called at application startup. In this case, implementation is simple:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
Because it’s standard, you’d expect to find the ConfigureAuth method defined in some class under the App_Start solution folder. It’s actually the Startup.Auth.cs file. Here’s what it looks like:
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"]
});
}
}
The app.Use* naming convention suggests the method adds a middleware implementation to the OWIN pipeline. In this case, the added middleware inspects the incoming request to see if the HTTP header Authorization contains a security token. This is how you secure a request according to the OAuth 2.0 bearer token specification (see bit.ly/W4OqA3). If it finds a token, it’s validated via a number of standard checks: Was the token issued by the intended authority? Has it been tampered in transit? Is it expired?
If the token looks good, the middleware projects its content in a principal, assigns the principal to the current user and cedes control to the next element in the pipeline. If the token doesn’t pass the checks, the middleware sends back the appropriate error code.
If there’s no token, the middleware simply lets the call go through without creating a principal. The authorization logic, typically in the form of authorization filters, uses the presence or absence of a principal (and its content) to decide whether the request should be served or access denied.
The single parameter passed to the middleware, WindowsAzureActiveDirectoryBearerAuthenticationOptions, supplies the settings for determining a token’s validity. It captures the raw values during project creation and stores them in the web.config file. The Audience value is the identifier by which the Web API is known to Windows Azure AD. Any tokens carrying a different Audience are meant for another resource and should be rejected.
The Tenant property indicates the Windows Azure AD tenant used to outsource authentication. The middleware uses that information to access the tenant and read all the other properties (such as which key should be used to verify the token’s signatures) that determine the validity of a token.
Those few auto-generated lines of code are all that’s needed to authenticate callers with Windows Azure AD. The only thing left to do on the Web API project is decorate with [Authorize] the methods you want to protect. Add it to all the methods in ValuesController. (For the sake of simplicity, I’m working with the default controllers that come with the template.)
Now, how do you verify that the Web API behaves as you intended? The simplest way is to create a test client.
Just as Windows Azure AD won’t issue tokens for Web APIs that haven’t been registered, Windows Azure requires all clients requesting tokens be registered as well. In order to get a token for a particular Web API, a registered client must also have been explicitly given access to that Web API in Windows Azure AD. Such design-time settings must be in place even before any user attempts authentication. Now I’ll show you how to use the Windows Azure portal to register a client application and create the permission that ties it to the Web API you created.
Start by accessing the Windows Azure portal. I’m going to authenticate to the same account I used earlier. To save time, I’ll navigate directly to the Windows Azure portal for my Windows Azure AD tenant. You obtain that URL by adding your tenant domain to the usual portal address, in my case https://manage.windowsazure.com/cloudidentity.net.
Navigating to the tenant-specific URL is quicker than hunting for the “Sign in with your organizational account” box from the general login page. Note that if the Windows Azure AD with which you’re working isn’t an admin or co-admin of your Windows Azure subscription, you’ll want to sign in to the portal using your usual credentials (a Microsoft Account or other organizational entity).
Once the portal loads, select the Active Directory icon from the list of available services, click on your directory and then on the Applications tab. You’ll see a list of all the applications you created, including the entry for the new Web API project. To create a new entry, click on the Add button from the command bar on the bottom of the page. You’ll see the dialog shown in Figure 4. Technically, you could define just about any kind of app and that would be a valid client for your Web API. Choose a native client application and move to the next screen.
Figure 4 The First Step of the Add Application Wizard on the Windows Azure Active Directory Portal
The next and last screen asks you to enter a redirect URI for the application. This URI is simply an identifier used during the OAuth 2.0 token acquisition flow to signal to the caller the interactive portion of the authentication process is over. The rest of the token acquisition process will proceed without user input. Depending on the platform on which you develop the native client, you might have to deal with different constraints. For example, a Windows Store app would require you to use the ms-app:// protocol schema if you want to use certain features (see details at bit.ly/13KrM6i).
In this case, I’ll write a classic .NET desktop app, which happens to be quite forgiving. Any valid URI will do. I used https://cloudidentity.net/myWebAPItestclient to ensure I’ll remember what this client is for.
As soon as I finalize the app entry, I see the page shown in Figure 5.
Figure 5 The Quick Start Page
The Update Your Code section provides information you’ll need when you write the client application. This includes the settings for the redirect URI and the client ID (a simple identifier), which you need when crafting a token request to the authority.
The Configure Access to Web APIs section offers a link to the area of the portal where you can specify the API to which the client should have access. If you follow the link, you’ll land on the application properties page shown in Figure 6. At the bottom you’ll see a dropdown that lets you specify the Web API you want your client to access. Notice the dropdown lists both the apps you defined and built-in APIs, specifically the Windows Azure AD Graph API.
Figure 6 The Native Client Application Properties Page on the Windows Azure Active Directory Portal
Choose the Web API project entry and hit Save. With that, everything is ready in Windows Azure AD to have a client obtain tokens for your service. Leave the browser open to that page, as you’ll need some of the data it will display.
You’re finally ready to create a test client and give the authenticated Web API a spin. You can create just about any client type, on any platform that offers an HTTP stack. To simplify the task of getting and maintaining tokens, Microsoft provides the ADAL, which makes it easy to authenticate against Active Directory (both Windows Azure and Windows Server) without having to become an expert in authentication protocols.
The library for the Microsoft .NET Framework has been released and is in developer preview for Windows Store. (For a tutorial on how to implement this scenario with a Windows Store app, see bit.ly/17YtYVg.) Eventually, there will be versions targeting all major client platforms.
Because the .NET version is already generally available, I’ll use it here. Apart from syntactic differences across different stacks, what you’ll learn here will be readily applicable to other platforms and application types. If you can’t wait, keep in mind that all communications in the scenario described here follow open standards and are documented in detail. You can code the token request logic pretty easily. For an example using Windows Phone 8, see bit.ly/YatATk.
The project is for a new Windows Presentation Foundation (WPF) application within the same solution, but you can choose any project type meant to run interactively with a user. After creating the project, I’ll add a button and a click event handler to trigger the Web API invocation logic.
The ADAL is distributed as a NuGet package. To add it to the client project, simply open the Package Manager Console from the Tools menu in Visual Studio and type Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 1.0.0. Now add the code in Figure 7 to the click event handler.
Figure 7 Code to Add to the Click Event Handler
private async void btnCall_Click(object sender, RoutedEventArgs e)
{
// Get token
AuthenticationContext ac = new AuthenticationContext(
"https://login.windows.net/cloudidentity.net");
AuthenticationResult ar =
ac.AcquireToken("https://cloudidentity.net/WindowsAzureADWebAPITest",
"a4836f83-0f69-48ed-aa2b-88d0aed69652",
new Uri("https://cloudidentity.net/myWebAPItestclient"));
// Call Web API
string authHeader = ar.CreateAuthorizationHeader();
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(
HttpMethod.Get, "https://localhost:44353/api/Values");
request.Headers.TryAddWithoutValidation("Authorization", authHeader);
HttpResponseMessage response = await client.SendAsync(request);
string responseString = await response.Content.ReadAsStringAsync();
MessageBox.Show(responseString);
}
Don’t worry if the code looks intimidating. It will all be clear in a minute.
The first line initializes a new AuthenticationContext. In the app’s code, an AuthenticationContext instance represents the authority with which to work. In this case, the authority is my Windows Azure AD tenant represented by the URI https://login.windows.net/\[mydomain\]. You’d use the same logic to connect to an on-premises directory by passing the address of its Active Directory Federation Services (AD FS) server (see bit.ly/1d553F0 for details).
The second line asks the AuthenticationContext for a token. There are many ways of crafting a token request—every scenario and application type calls for different parameters. In this case, I want to specify the resource for which I want a token is my Web API. So I pass the identifier of its Windows Azure AD entry. This is the same value used as the audience in the Web API project. Then, because it’s the native client requesting the token, I need to pass in the client ID and the redirect URI of my client from the app configuration page I left open in the browser.
That’s all I need to do to obtain a token. The rest of the code puts that token in the correct HTTP header according to the OAuth 2.0 specification, and performs the actual call.
Now give the solution a spin. After changing the solution to start all projects at once, press F5. As soon as the execution hits the call to AcquireToken, you’ll get the authentication dialog shown in Figure 8. ADAL takes care of contacting the right endpoint and rendering the authentication experience provided by the server in a pop-up dialog without requiring you to write any UI code.
Figure 8 The Active Directory Authentication Library Authentication Dialog
When I provide the credentials of any valid user from my directory tenant, I get a token back. The subsequent code presents the token to the Web API in the request headers. The security middleware validates it. Because all validation parameters are a match, it sends back HTTP status code 200 with the results, successfully concluding the proof of concept for this scenario.
Just for kicks, click the button again. You’ll see this time you get a token back right away, without being prompted. That’s because ADAL has a built-in token cache that keeps track of the tokens. It even takes care of silently refreshing expired tokens whenever possible.
I’ve barely scratched the surface of what you can accomplish with Web API, the Microsoft OWIN components, Windows Azure AD and ADAL. The tokens issued by Windows Azure AD aren’t simply proofs of authentication. They carry rich user information you can easily access from the user’s principal and use for sophisticated authorization logic. The authentication process can go far beyond the username and password shown here.
From multiple authentication factors to seamless single sign-on in federated scenarios, the possibilities are endless. Integrating with the Graph API can give you access to a treasure trove of features. You can query the directory for information that goes beyond the currently authenticated user, from simple people picker functionality to advanced organizational structure crawling.
Those features can add to the functionality of cloud-based Web APIs. Until now, you had to run them on-premises behind the corporate firewall. You can also use similar code with Windows Server Active Directory, in one of the clearest examples of cloud and on-premises symmetry of capabilities.
Of course, you can also publish the Web API to Windows Azure without changing a single line of code—the authentication features will keep working. The only thing you’d need to change is on the client project. The URL of the service will change according to the new application location. However, the logic for acquiring a token can remain exactly the same, because the resource identifier doesn’t have to be tied to the physical address of the resource.
Vittorio Bertocci is a principal program manager on the Windows Azure AD team, where he looks after developer experience. Bertocci is well known in the developer community for his decade-long evangelism activities about identity and development via his books, his sessions at major conferences, his blog (cloudidentity.com) and Twitter feed (twitter.com/vibronet).
Thanks to the following Microsoft technical experts for reviewing this article: Howard Dierking and Daniel Roth
Howard Dierking is a program manager on the Windows Azure Frameworks and Tools team where his focus is on ASP.NET, NuGet and Web APIs. Previously, Dierking served as the editor in chief of MSDN Magazine, and also ran the developer certification program for Microsoft Learning. He spent 10 years prior to Microsoft as a developer and application architect with a focus on distributed systems.
Daniel Roth is a senior program manager on the Windows Azure Application Platform team currently working on the ASP.NET Web API. Prior to working on ASP.NET he worked on WCF, starting when it first shipped in .NET Framework 3.0. His passions include delighting customers by making frameworks simple and easy to use.