次の方法で共有


Windows Azure Authentication Library: a Deep Dive

We are very excited today to announce our first developer preview of the Windows Azure Authentication Library (AAL).
For an overview, please head to Alex’s announcement post on the Windows Azure blog: but in a nutshell, the Windows Azure Authentication Library (AAL) makes it very easy for developers to add to their client applications the logic for authenticating users to Windows Azure Active Directory or their providers of choice, and obtain access tokens for securing API calls. Furthermore, AAL helps service authors to secure their API by providing validation logic for incoming tokens.
That’s the short version: below I will give you (much) more details. Although the post is a bit long, I hope you’ll be pleasantly surprised by how uncharacteristically simple it is going to be Smile

Not a Protocol Library

Traditionally, the identity features of our libraries are mainly projections of protocol artifacts in CLR types. Starting with the venerable Web Services Enhancements, going through WCF to WIF, you’ll find types representing tokens, headers, keys, crypto operations, messages, policies and so on. The tooling we provide protects you from having to deal with this level of detail when performing the most common tasks (good example here), but if you want to code directly against the OM there is no way around it.
Sometimes that’s exactly what you want, for example when you want full control over fine grained details on how the library handles authentication. Heck, it is even fairly common to skip the library altogether and code directly against endpoints, especially now that authentications protocols are getting simpler and simpler.

Some other time, though, you don’t really feel like savoring the experience of coding the authentication logic and just want to get the auth work out of your way ASAP and move on with developing your app’s functionality. In those cases, the same knobs and switches that make fine grained control possible will likely seem like noise to you, making harder to choose what to use and how. 

With AAL we are trying something new. We considered some of the common tasks that developers need to perform when handling authentication; we thought about what we can reasonably expect a developers knows and understand of his scenario, without assuming deep protocol knowledge; finally, we made the simplifying assumption that most of the scenario details are captured and maintained in a Windows Azure AD tenant. Building on those considerations, we created an object model that – I’ll go out on a limb here - is significantly simpler than anything we have ever done in this space.

Let’s take a look about the simplest model a developer might have in his head to represent a client application which needs to securely invoke a service and relying on one identity as a service offering like Windows Azure AD.

  • I know I want to call service A, and I know how to call it
  • Without knowing other details, I know that to call A I need to present a “token” representing the user of my app
  • I know that Windows Azure AD knows all the details of how to do authentication in this scenario, though I might be a bit blurry about what those details might be

image

…and that’s pretty much it. When using the current API, in order to implement that scenario developers must achieve a much deeper understanding of the details of the solution: for example, to implement the client scenario from scratch one developer would need to understand the concepts covered in a lengthy post, implement it in details, create UI elements to integrate it in your app’s experience, and so on.

On the server side, developers of services might go through a fairly similar thought process:

  • I know which service I am writing (my endpoint, the style I want to implement, etc)
  • I know I need to find out who is calling me before granting access; and I know I receive that info in a “token”
  • I know that Windows Azure AD knows all the details of the type of token I need, from where, and so on

Wouldn’t it be great if this level of knowledge would be enough to make the scenario work?
Hence, our challenge: how to enable a developer to express in code what he or she knows about the scenario and make it work without requiring to go any deeper than that? Also, can we do that without relying on tooling?

What Can you Do with AAL?

If you are in a hurry and care more about what AAL can do for you than how it works, here there are some spoilers for you: we’ll resume the deep dive in a moment.

The Windows Azure Authentication Library is meant to help rich client developers and API authors. In essence, the Windows Azure Authentication Library helps your rich client applications to obtain a token from Windows Azure Active Directory; and it helps you to tell if a token is actually from Windows Azure Active Directory. Here there are some practical examples. With AAL you can:

  • Add to your rich client application the ability to prompt your users (as in, generate the UI and walk the user through the experience ) to authenticate, enter credentials and express consent against Windows Azure AD directory tenants, ADFS2 instances (or any WS-Federation compliant authority), OpenID providers, Google, Yahoo!, Windows Live ID and Facebook
  • Add to your rich client application the ability to establish at run time which identity providers are suitable for authenticating with a given service, and generate an experience for the user to choose the one he or she prefers
  • Drive authentication between server-side applications via 2-legged OAuth flows
  • If you have access to raw user credentials, use them to obtain access tokens without having to deal with any of the mechanics of adapting to different identity providers, negotiating with intermediaries and other obscure protocol level details
  • If you are a API author, easily validate incoming tokens and extract caller’s info without having to deal with low level crypto or tools

Those are certainly not all the things you might want to do with rich clients and API, but we believe that’s a solid start: in my experience, those scenarios take on the fat part of the Pareto principle. We are looking into adding new scenarios in the future, and you can steer that with your feedback.
All of the things I just listed are perfectly achievable without AAL, as long as you are willing to work at the protocol level or with general purpose libraries: it will simply require you to work much harder.

The Windows Azure Authentication Library

The main idea behind AAL is very simple. If in your scenario there is a Windows Azure AD tenant somewhere, chances are that it already contains most of the things that describe all the important moving parts in your solution and how they relate to each other. It knows about services, and the kind of tokens they accept; the identity providers that the service trusts; the protocols they support, and the exact endpoints at which they listen for requests; and so on. In a traditional general-purpose protocol library, you need to first learn about all those facts by yourself; then, you are supposed to feed that info to the library. 
With AAL you don’t need to do that: rather, you start by telling to AAL which Windows Azure tenant knows about the service you want to invoke. 

Once you have that, you can ask directly to the Windows Azure AD tenant to get for you a token for the service you want to invoke. If you already know something more about your scenario, such as which identity provider you want to use or even the user credentials, you can feed that info in AAL; but even if all you know is the identifier of the service you want to call, AAL will help the end user to figure out how to authenticate and will deliver back to your code the access token you need.

Object Model

Let’s get more concrete. The Windows Azure Authentication Library developer preview is a single assembly, Microsoft.WindowsAzure.ActiveDirectory.Authentication.dll,

It contains both features you would use in native (rich client) applications and features you’d use on the service side. It offers a minimalistic collection of classes, which in turn feature the absolute essential programming surface for accomplishing a small, well defined set of common tasks.

Believe it or not, if you exclude stuff like enums and exception classes most of AAL classes are depicted in the diagram below.

 

image

Pretty small, eh? And the best thing is that most of the time you are going to work with just two classes, AuthenticationContext and AssertionCredential, and just a handful of methods.

Clients

Let’s start with the client. AuthenticationContext is what you use for identifying the Windows Azure AD tenant that knows about your target service. Once initialized, you can use its Acquirexxx methods to obtain a token for the target service. Occasionally you’ll do so by feeding in an instance of one class in the Credential hierarchy (more details in the scenario section). Upon successful authentication, Acquirexxx will return an instance of AssertionCredential, which contains the access token for the target service as returned by Windows Azure AD. At that point, it is up to you to decide how to use it: if you want to use OAuth2 AssertionCredential offers a nice method CreateAuthorizationHeader, which will create a string of the form “bearer …” ready to be put in the HTTP Authorize header; if you want to use any other protocol, you can get the raw bits of the token directly from AssertionCredential and use them according to whatever protocol schema you deem most appropriate. Want to see that in code? There you go:

  1: AuthenticationContext _authContext = 
  2:  new AuthenticationContext("https://humongousinsurance.accesscontrol.windows.net");
  3: AssertionCredential theToken =
  4:  _authContext.AcquireUserCredentialUsingUI("urn:InteractiveAuthentication");
  5:  
  6: HttpWebRequest request =
  7:   WebRequest.Create("https://localhost:34000/Interactive/api/shipment") as HttpWebRequest;
  8: request.Method = "GET";
  9: request.Headers["Authorization"] = theToken.CreateAuthorizationHeader();
  10: request.ContentType = "application/json";
  11: HttpWebResponse response = request.GetResponse() as HttpWebResponse

There are only 3 lines of AAL code here, I just had to break them down to fit the silly theme of this blog (I’ll have to change it one of these days).

  • lines 1-2 initialize the authentication context to an ACS namespace, “humongousinsurance”
  • lines 3-4 ask for a token for a service  identified by its realm string, “urn:interactiveauthentication”. At this point AAL displays a UI for helping the end user to authenticate with their provider of chocie: more about that later.
  • lines 6-8 prepare the necessaire for emitting a REST call to the service
  • line 9: the access token from 3-4 is serialized an a header and assigned to the request
  • lines 10 and 11 finalize and perform the call

That’s all there is to do on the client! Of course I am looking forward to hear your feedback about whether this fits the bill in term of ease of use, however here there’s why I am optimistic about this being actually a pretty usable solution:

image

That’s right! The concepts exposed by the object model live at the same level of abstraction you can expect from a developer without domain-specific knowledge; and thanks to the Identity as a Service approach, we can operate approximately at that level and still get things done without having to leak the abstraction.

Before moving to describe how AAL tackles the service side, I’d like to add a couple of forward-looking details:

  • One aspect concerns the dynamic discovery of some of the settings that AAL needs in order to obtain tokens, such as your Windows Azure AD tenant. In the Developer Preview the developer is expected to find out about the correct value on his or her own. Moving forward, we will offer a discovery mechanism which will help you to find out automatically which tenant should be used for authenticating against a given service, and even which instance of Windows Azure AD should be used.
  • Another important aspect concerns the use of the OAuth2 client_id parameter for describing your client applications to Windows Azure AD. In the current developer preview we do not require you to pass that info, which means that we treat clients as transparent user agents (i.e. we authenticate and authorize only depending on who the user is, and ignore the app he is accessing resources from). Moving forward, we will add the ability to specify the client_id and influence the authentication and consent behavior accordingly .

Services and API

The service side is, in the best case, even simpler. The task that AAL helps you to perform as services and API author is validating an incoming token and, upon successful authentication, provide you with a representation of the user. Once again, you start by specifying which Windows Azure AD tenant is responsible for issuing tokens for your service, by initializing an AuthenticationContext. Done that, the absolute minimum extra info you need to provide is the identifier of your service: you need to ensure that the request was really intended for you. You can’t get that automatically form the tenant because the tenant itself might be protecting many different services at the same time, and cannot know which specific service you are working on right now. The good news is that, in the best case, now you already have all you need to validate requests to your service. In code:

  1: var authenticationContext = 
  2:   new AuthenticationContext("https://humongousinsurance.accesscontrol.windows.net");
  3: authenticationContext.Options.Audiences.Add(
  4:   "urn:InteractiveAuthentication"});
  5: Thread.CurrentPrincipal = 
  6:   authenticationContext.AcceptToken(token);

Once again, just three lines broken in 2 for formatting purposes. Details:

  • lines 1-2 initialize the authentication context to an ACS namespace, “humongousinsurance”
  • lines 3-4 add to the context the expected audience of the service being implemented, so that incoming tokens can be validated against it
  • lines 5-6 validate the token. Upon successful validation, a new ClaimsPrincipal is created and assigned to the current thread

Wait, did I say ClaimsPrincipal? Yes I did. On the service side AAL represents identities as ClaimsIdentity, just like WIF. In fact, the developer preview has a dependency on WIF 1.0 runtime (though if you only develop on the client you might never realize it, given that the only type from Microsoft.IdentityModel instantiated by AAL is exactly for the claims principal.

At this point I should raise that the way in which the AAL developer preview handles the service side of scenarios does not precisely reflect where we want to be going forward. To be more specific: we are absolutely convinced that we need to deliver on the ease of use and simplicity you see here, which is why you are getting this feature in the preview today. However we would like to be able to release service side features and client side features in independence, and reduce as much as we can interdependencies that might make things more difficult for you: which is why moving forward you might see us delivering service side features as WIF extensions, and keep AAL as a client-only deliverable.

On Extensibility

As you might have guessed, achieving this level of simplicity comes with some tradeoffs. One such tradeoff – which you might find unusual if you are an identity expert and used to work with protocol libraries – is the near total absence of extensibility points. We are very serious about usability, and felt that adding extensibility would have made difficult to maintain the abstraction level we achieved and would have degraded the signal/noise ratio in AAL’s API surface. Luckily, if you want something that AAL does not offer out of the box you are anything but stuck. In fact, you have many options:

  • You can use WIF (or equivalent on other platforms). WIF is most definitely a protocol library, and offers a staggering gamut of extensibility options. Pretty much anything that AAL does can be re-done in WIF, if you are willing to put in the work: and if you do, you’ll be able to customize anything in the process
  • You can code directly at the protocol level. If you understand al the moving parts involved, you can skip the library part altogether and code directly against the endpoints. Even more work, but even more control
  • You can give us feedback! What you are looking at now is only our first preview: we still have a lot of work to do before declaring that done, and I fully expect that your feedback will help us to evolve and extend AAL in the right direction

Finally, in the future you’ll have one more option. We are planning to release future drops of AAL under an open source license, which will allow you to fork and tweak the code as needed.

On AAL’s Native Core

At its heart, the developer preview of AAL is written in native code. Microsoft.WindowsAzure.ActiveDirectory.Authentication is a mixed mode assembly, compiled for a specific “bitness”: that’s why AAL comes in two NuGets, in x86 and x64 flavors.That will require some attention when choosing which package is right for your application, your development environment and whether you need to switch package before deploying to machines with different architectures. Also, that means that wherever you go you’ll need to bring with you the VC runtime.

In the developer preview AAL has a native core because it shares some code with other libraries that are being used for claims-enabling other products: however that’s only a temporary situation, future drops of AAL will be fully managed and all the constraints mentioned earlier will disappear. 

On ACS Namespaces vs. Directory Tenants

One last thing on the object model. If by any chance you read the 22 printed pages tome I wrote when we first released the Windows Azure AD developer preview, you already know that right now there are differences in how ACS namespaces and Directory tenant operate: available identity providers, available endpoints, format used for specifying realms and issuers, and so on. I am very happy to say that AAL uses the exact same object model to work with both tenant types: the only differences are in the strings that you’ll use for representing the tenant itself, the target service realm, and so on. You can easily see thins for yourself: the AAL developer preview samples come with instructions which show how you can point the solution to work with an ACS namespace or a directory tenant, and that does not require any AAL code changes.

That said, there are still differences in term of capabilities that will somewhat surface through your application’s behavior: for example, a rich client targeting a service which trusts a directory tenant will only be able to authenticate against directory tenants and won’t have access to the IPs that are available on ACS.

The good news is that the capabilities of the two tenant types are converging, and that you can handle the interim directly in your code (for example by creating more than one AuthenticationContext and connecting to multiple tenants of different types)

Main Scenarios

Here I’d like to give you a hint of the main scenarios we are demonstrating in the AAL samples on MSDN. Every sample comes with detailed readmes, and I’ll come back to the topic in the next days; hence I won’t get too deep. Also, I’ll concentrate on the client (as in requestor) side of the scenario as it is the newest. I’ll talk of the service side in more details in future posts.

Here there’s a succinct decision diagram which illustrates pretty much all the main ways you can use AAL to code authentication for a client application:

image

The next three sections will look at the three branches, breadth first.

User Authentication via Browser Dialog

If you want to invoke your target service as the interactive user of your application, but you have no direct knowledge of their credentials  or even of which identity provider they should authenticate to, then you are on the red branch of the flowchart. This also happens to be the case I used for explaining the object model, so you know almost everything about this flow already Smile although you are still missing a very important piece: what exactly was shown to the user during the call AcquireUserCredentialUsingUI?

image

In what we sometimes call the interactive mode, AAL pops out a dialog from the calling application. That dialog is used for rendering the list of identity providers that Windows Azure AD knows are suitable for accessing the target service. The flow in the figure shows two possible authentication experiences, one with a local ADFS and the other thru Google, which are fully driven by the end user’s choices. From the developer perspective, that’s still just one line of code. The use of a browser grants incredible flexibility to all the parties involved. For example, the identity providers can decide to change their way of gathering credentials or add extra consent steps: thanks to this approach they are free to make those changes available instantly to all their clients, without pushing out updates if their experience would be handled by a native UI. If you want to know more about the advantages of this approach, read the intro of this.

FI you want a 20,000ft view, the general arch of this scenario looks like the following:

image

The flow is pretty straightforward. The only caveat in the preview is that you either use an ACS namespace (which give you all the usual IPs but not directory tenants) or a directory tenant (which gives you the exact opposite). For example, the experience for one directory tenant would look like something of this find:

image

The sample showing this scenario in action is here. It is pre-provisioned to use an ACS namespace, but there are all the instructions you need to point it to a directory tenant if you want to.

Authentication via User Credentials

If you are still accessing the target service as your user, but this time you do have access to the user credentials, you are in the green branch of the flowchart.

The scenario always starts with creating the AuthenticationContext; however it is then followed by creating a CredentialObject of the right time, that is to say a UsernamePasswordCredential or a KerberosCredential. That credential must be scoped to the identity provider that is competent to validate it; however you don’t need to know the exact endpoint, you just need to know the domain that is being used to represent that IP in ACS. Once you created that Credential, you pass it to the AutenticationContext in the AcquireToken, together with the target service realm as in the interactive case. From that point on, it’s business as usual. Diagram:

image

You’ll occasionally hear me referring to this scenario as the “non-interactive” one, because AAL itself does not drive any user experience. Of course your app can be interactive, for example by showing a dialog of your own making which gathers username and password, hence this definition is confusing and I am trying to stop using it; however I just know I will occasionally use it so I prepared you just in case Smile

The sample showing this scenario is here.

Service to Service Authentication

Now, who says that in order to be a client one has to run on a client? There are many scenarios in a server side process - say a long running process polling some service – which are clients of other services. That’s the orange branch of the decision flowchart. Operatively, this is exactly the same as the scenario we just described: the only difference is that in this case the client application does not invoke a service as a user, but as itself. That requires the use of specific kind of credentials, as established by service identities (for ACS tenants) and service principals (for directory tenants) but modulo the types the drill is exactly the same,

 

image

Our sample demonstrating this scenario is here. The solution has some moving parts which deserve a closer look, please make sure to read the readme and if you still have questions I’ll do a blog post just on it.

Interestingly, the Graph API in itself is an excellent example of server to server authentication.  In fact, few days ago we got together with Ed and updated his sample to use AAL instead of custom protocol code: we basically ended up saving almost 700 lines of code Smile that made my day!

What’s Next

Well, for an introductory post I’d say we covered a lot of ground! We’ll keep talking about AAL: here I just mentioned the main cases, but there are few others that albeit less common I believe will be interesting to touch. Also, here I almost totally neglected the service side and that definitely needs fixing! Smile

For the time being, I’d encourage you to check out the resources in the developer preview, read the docs in MSDN and especially hit the Windows Azure AD forums with lots and lots of feedback. We are trying something new here, and your feedback is especially important. Thanks in advance and happy AAL coding!

Comments

  • Anonymous
    August 09, 2012
    The comment has been removed
  • Anonymous
    August 15, 2012
    Great article. But any inputs on using this library on windows 7 phone?