First published on MSDN on May 02, 2017
Authored by Andreas Helland
"This whole Azure AD thingy sounds complicated - aren't there any libraries or something to make life simpler?"
Well, I suppose not everyone wants to write everything from scratch 🙂 Short answer: yes, there are libraries. Long answer: there are a number of libraries to choose between.
Actually, before committing to a library you need to answer a couple of questions for yourself. Which platform am I working on? What kind of interaction do I have with Azure AD? Having an iOS app where a user signs in with their social id is sort of different than a daemon app running server-side authenticating with corporate credentials.
There are two distinct "things" you will usually want to do with AAD:
- Use it for authentication and authorization purposes.
- Use the data it contains (user attributes, group memberships, etc.).
Let's start with the second area of interest first (because it's easier to deal with). The data in AAD is accessible through two API sets; the AAD Graph, and the Microsoft Graph. Both are RESTful, and play nice with anything that can speak HTTP.
Since both the new and old Graphs work with plain HTTP you don't require libraries to work with it. Whatever your platform is, whatever language you code in, it should be fairly easy to achieve the basics. (For the sake of discussion I'm assuming access to the API is already taken care of.)
You have the GraphClient for targeting the AAD Graph:
https://www.nuget.org/packages/Microsoft.Azure.ActiveDirectory.GraphClient/
And for the Microsoft Graph there is a similar-sounding client too;
https://www.nuget.org/packages/Microsoft.Graph
If you want to leverage both the old, and the new Graph you need to make sure you keep track of which using statement goes where. As the naming can be similar you might choose the wrong one. It will still compile, but may throw an exception during run-time instead.
Should you use these? Well, I have had projects where I used them but I have also had projects where I chose not to use them. If you know that you only need a very specific object type from AAD, and handle full control over the token handling pieces it may very well be easier just doing it in code you write yourself.
The boring part of this is creating the model classes. What I usually do is use the Graph Explorer to see an example output in json, and then head over to json2sharp ( http://json2csharp.com/ ) to create the code for me 🙂
I have no problem recommending using either of them though. They are easy to start with, and if you don't want to dive into the details of the objects IntelliSensing your way through these should get you to a working state.
When it comes to authentication and authorization the outlook changes slightly. We're still talking about HTTP and standards, so you're not forced to use librabries, and can roll your own. But should you (roll your own that is)? My general recommendation about writing security-related code is still that you should not do this unless you really know what you're doing. (Exceptions to this rule? Yes, there are, and I will get back to this.)
If you want to follow the generally recommended path, (using code already written by pros), Microsoft pretty much has you covered:
https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-lib...
Looks good - so I basically just need to refer to this table, and we are golden? Yes, possibly. Or maybe not, depending on your use case. Remember how I mentioned that there is a v1 and a v2 endpoint for AAD? ( https://blogs.msdn.microsoft.com/azuredev/2017/02/14/azure-ad-developer-tips-and-tricks-part-2/ )
ADAL targets the v1 endpoint, and one of the nuances to be aware of is that while this endpoint is based on OAuth it isn't actually fully compliant in all areas. ADAL obviously hide some of these details for you, but if your main focus is on Android and iOS apps these operating systems are making it harder to implement "fancy" auth UIs on the device without being compliant. Your basic sign-in will work, but if you want cross-app SSO and such things it's getting more tricky. I'm not going to dive into these details here; you just need to be aware of this in your planning/POC phase.
So what do we actually do about this? The v2 endpoint is compliant with the standards, but you're not able to coax ADAL into using this. Microsoft actually has a library going here as well - the Microsoft Authentication Library (MSAL):
https://www.nuget.org/packages/Microsoft.Identity.Client/
Is the "Alpha" moniker uncomfortable? I agree, this is annoying, and there is of course a reason for it being in this stage. It isn't feature complete, or bug-free. And what if I am not doing something like a UWP app? The trend we're seeing is that there are third-party OAuth libraries popping up for Android and iOS, and since the v2 endpoint is compliant I would actually recommend you consider using one of these third-party options. (I have seen it working, so I know it can be done.) Unless there are other v2-blockers stopping you. ( https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-limitations )
Will MSAL actually progress, or should I just ditch it altogether? It is being developed, although at a slightly slower pace than I would like. If you are targeting "regular" AAD you can stick with the ADAL and v1 story for now if you like. If however you are into AAD B2C you might want to pay attention to it, because the scope of B2C requires compliancy with standards to have the different IdPs play nice with each other.
I alluded to there possibly being exceptions to the recommendation of not re-inventing the wheel with your own code. The interactive OAuth flows are typically what most devs will find a hassle to implement when getting started with AAD. You need to build code sending a web view to AAD with the proper parameters, and handle AAD redirecting to a URI afterwards parsing the responses correctly. Yes, this can be implemented by you provided you have the necessary knowledge of the platform - but in many cases this is easier with using ADAL/MSAL.
But maybe you don't have an interactive flow. What if we're talking about that daemon app I mentioned previously? Maybe it's the password grant flow you find most useful for this. And that isn't super-complicated to pull off:
[code language="csharp"]
HttpClient client = new HttpClient();
string requestUrl = $"https://login.microsoftonline.com/{domain}/oauth2/token";
string request_content = $"grant_type=password&resource={resource}&client_id={clientId}&username={user}&password={pw}&scope=openid";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
try
{
request.Content = new StringContent(request_content, Encoding.UTF8, "application/x-www-form-urlencoded");
}
catch (Exception x)
{
var msg = x.Message;
txtOutput.Text = $"Something went wrong: {msg}";
}
HttpResponseMessage response = await client.SendAsync(request);
string responseString = await response.Content.ReadAsStringAsync();
GenericToken token = JsonConvert.DeserializeObject<GenericToken>(responseString);
var at = token.access_token;
[/code]
And, if you found that you needed to use the client credentials flow instead you would basically just change the grant type. On the other hand - the ADAL code for using the client credentials flow is also fairly lightweight:
[code language="csharp"]
public static async Task<string> AcquireTokenAsyncForApplication()
{
AuthenticationContext authenticationContext = new AuthenticationContext(Constants.AuthString, false);
// Config for OAuth client credentials
ClientCredential clientCred = new ClientCredential(Constants.ClientId, Constants.ClientSecret);
AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(Constants.ResourceUrl,
clientCred);
string token = authenticationResult.AccessToken;
return token;
}
[/code]
As you can see there is no right or wrong answer here. Do you need the full control of the HTTP messages, with as few lines of code as possible? Or is it more important to have a working piece of code rather than the fully optimized version?
Playing around with both is probably the best approach. And of course - there's nothing wrong with capturing the traffic generated by the libraries to understand what's going on, and adapting it accordingly.
So, summarizing this we have the following basic options when working with Azure AD:
- GraphClient (AAD Graph).
- GraphClient (MS Graph).
- ADAL (AAD v1).
- MSAL (AAD v2).
- I don't need no pre-written code to get my program working.
It's not necessarily that hard to choose, or even landing on the right choice by sheer luck, but it can be confusing when you see references to different libriaries in docs and articles. And if you do things like requesting a token for the AAD Graph, and then use the library for the MS Graph, it can lead to a round of troubleshooting before you figure out what's wrong. "I'm using MS libraries - why won't it work?!"
Sure, but who hasn't been in a situation where one MS component refuses to work with another MS component? Keep calm, and keep using Azure AD 🙂
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.