AAL becomes ADAL: Active Directory Authentication Library
Today we are releasing a new developer preview of our Windows Azure Authentication Library (AAL) Active Directory Authentication Library (ADAL). You can find the NuGet package here.
This refresh introduces many new features which we believe will boost your productivity even further! Below there’s a list of the most salient news.
New Assembly Name & Namespace
When we first introduced AAL, the only authorities you could leverage were Windows Azure AD tenants and ACS namespaces: hence the name Windows Azure Authentication Library (AAL) was correct and descriptive, if I can say so myself.
At //BUILD/ last June we finally disclosed that ADFS in Windows Server 2012 R2 preview supports OAuth2 and JWT tokens, and demonstrated that our libraries work with both on-premises and cloud authorities alike. Therefore, to ensure that such capability is reflected in the name of the library we are renaming it to Active Directory Authentication Library (ADAL).
Furthermore: as we did for the JWT handler, we are moving ADAL to live under the System.* namespace. The new path is System.IdentityModel.Clients.ActiveDirectory.
Once again, we believe this will help to clarify the role of the library and its scope while at the same time improving discoverability.
This change will apply to the Windows Store library as well: the next refresh will use the new name, too.
Note: we are not going to eliminate the existing AAL right away, just to give time to all the people using it (including the ASP.NET tools!) to move off it. For some time the two will coexist in the NuGet gallery, which might end up being a bit confusing. We hope to keep that transition time as short as possible.
New features
Let’s take a look at some of the details.
Support for Windows Server 2012 R2 ADFS On-Premises for OAuth2 flows
As mentioned this is not really a new feature, but now we can finally talk about it! If you want to play with it, you can easily adapt those instructions to use ADAL .NET instead of a Windows Store client.
Support for the Common Endpoint
Until now, in order to use ADAL with Windows Azure AD you had to find out which tenant should be used for requesting tokens, as it was a mandatory parameter for initializing AuthenticationContext.
Windows Azure AD does offer a mechanism for authenticating a user without specifying upfront the tenant he/she belongs to: it’s the famous “common” endpoint we use in the multitenant web applications walkthrough. I also talk about it here.
In this refresh ADAL allows you to use the common endpoint for initializing AuthenticationContext: you just pass “https://login.windows.net/Common” as Authority. The result is a late-bind AuthenticationContext; basically, the actual authority remains unassigned until the first call to AcquireToken. As soon as the user authenticates to a given tenant, such tenant becomes the authority for that AuthenticationContext instance.
This is going to be super-handy for simplifying your clients, given that you don’t need to add logic or config that figures out in advance which tenant should be used (though there will always be situations in which that might be the right thing to do). Our updated Windows Azure AD sample demonstrates this.
UPN & Tenant Info in AuthenticationResult
The support for common endpoint is enabled by another new feature: we now return the user’s UPN and origin tenant within AuthenticationResult.
This enables you to find out in your code who signed in and where “after the fact”. This is key for allowing you to create dynamic experiences: for example, you can find out who signed it at a certain point, and plug it back in as login_hint in subsequent AcquireToken calls to ensure that you are acting as the same user across multiple operation. Moreover, you’ll be able to work with scenarios in which a generic application can be tailored at run time to any tenant. What’s more, this allows you to handle multiple users and multiple tenants at once! Moving forward, we will publish samples demonstrating how to take advantage of this new feature in advanced scenarios.
This feature was also key for enabling us to properly store tokens when we acquire them via common endpoint, for which we don’t know in advance user and tenant (important components of the cache key). That’s a great segue for the next new feature
Improved Cache
ADAL now features an in-memory cache out of the box. This is on par with what we offer in the Windows Store version, with the main difference that tokens are stored in memory and are cleared up when the hosting application closes.
The presence of the cache means that now you no longer need to hold on the access tokens you obtain: you can just call AcquireToken every time you need a token, knowing that ADAL will return a cached access token or take care of refreshing it for you.
The cache is also significantly simpler to use than the one in the Windows Store library. The store itself is just an IDictionary<string,string>, which you can query and manipulate just like any collection. The cache key is a composite of the various parameters used to obtain the token (resource ID, client ID, user, tenant/authority…) and the default in memory cache encodes it in a single value: however we provide a class to help you unpack it, TokenCacheEncoding, so that you can query and manipulate the token collection to your heart’s content. For example, say that you want the list of all the users who have a token in your cache. All you need to write is the following:
IDictionary<string, string> cache = myAC.TokenCacheStore; var users = cache.Keys.Select( key => TokenCacheEncoding.DecodeCacheKey(key).User).Distinct();
where myAC is an AuthenticationContext instance.
Of course, plugging in your own cache is very easy. We expect you’ll create your own cache implementations to accommodate the specific storage you want to use: e.g. a desktop app will save tokens differently than a middle tier one.
That will also be handy to help you define the boundaries you want between applications. You can share the same cache across multiple AuthenticationContext or even processes, if your scenario calls for it; or enforce isolation by using different cache stores for context switches such as in multitenant apps.
Our updated Windows Azure AD sample shows how you can build a custom cache to save your tokens in CredMan; very handy!
ForcePrompt
ADAL does its best to reduce the number of times in which the end user is prompted. The cache, and in minor measure the session & permanent cookies accessible from the browser window, can do a great job to keep prompts after control.
There are, however, situations in which you want your user to be prompted. For example: think of something like a management console, which can manipulate resources associated to different users or even tenants. Occasionally you’ll want to make sure that your end user is allowed to select which account should be used: for example when a new resource is added, or if the operation requested requires selecting a user with higher privileges. To that end we added ForcePrompt: it’s a new parameter in AcquireToken which allows you to tell ADAL to ignore whatever cached token or cookie that might be a fit for the requested resource, and ensure that the end user has the chance of selecting the desired account (or even add a new one). It’s very easy to use, just look for it in the AcquireToken overloads.
Note: ForcePrompt is only available for those overloads where there is uncertainty about which user could be used. That does not include cases in which the user is specified (via login_hint) or a set of credentials (tied to a specific identity, too) are provided.
ACS without HRD page
Since its very first preview, ADAL .NET offered the ability of obtaining tokens from your ACS namespaces. ADAL featured a local version of ACS’ default home realm discovery page, optimized for the browser dialog real estate (small layout, links to the external providers selecting the mobile/touch enabled experiences). Although that was great as a quick tool for development time, we didn’t think that it would have been an experience you would have wanted to use in production. At the same time, the nature of a native client is simply not conducive of customizing the experience via a Web page as it is instead the case when you use ACS with a Web application.
As a result, we decided to eliminate that locally-generated page and allow you (when your scenario calls for it, in many cases it does not) to create a home realm discovery experience native to the UX stack of your application. The ability of signing in with social providers or federated ADFS instances remains unchanged, the only part that’s different is the identity provider selection. Our updated ACS sample demonstrates the new approach.
As more ACS features light up in Windows Azure AD tenant, the Web-based IdP selection might return: but in that case you can expect it to be far more seamlessly integrated with the rest of the platform.
Broad Use Refresh Tokens
Windows Azure AD can issue refresh tokens that can be used not only for renewing the access token with which they were originally issued. That largely means that in those cases you only need to authenticate to obtain an access-refresh tokens tuple once, and access tokens for other resources within the same tenant will be obtainable silently via the first refresh token. I like to call those broad use refresh tokens: I am not sure if the term will stick, we’ll see once we get our official MSDN reference out (soon!).
ADAL .NET supports the use of refresh tokens: once you have one in the cache, ADAL will take care of using it even when you request tokens for new resources. The entire process is fully transparent, very handy.
Next Steps
From now on, you can expect us to do mostly stabilization work on ADAL .NET. We already know of a couple of small changes we want to put in before calling it done, but they should be largely transparent to you. We’re almost there, folks!
Please give the new ADAL .NET a spin and let us know if the new features are useful in your scenarios, your input will be invaluable to help us through the last sprint!
One Comment