Azure AD Developer Tips and Tricks – Part 2
Published Feb 12 2019 02:33 PM 459 Views
Iron Contributor
First published on MSDN on Feb 14, 2017

Authored by Andreas Helland


I kind of left you hanging in the last part when I said there could be a need for "going straight to the source in the form of GraphExplorer, or doing REST calls manually". Let's continue where we left off, and do something about that shall we?

As an Azure AD developer you will quite often need to peek behind the UI bits to see what's actually going on. To paraphrase a saying from a different ecosystem - there's a web app for that . The app I am thinking about is the GraphExplorer ; which, you guessed it, comes in an old and a new version just to introduce another confusion factor :)

GraphExplorer v1 - https://graphexplorer.cloudapp.net



GraphExplorer v2 - https://graph.microsoft.io/en-us/graph-explorer/



And of course you can use whichever RESTful-utility you want to if you don't like the prebuilt offering. I hear good things about Postman, but personally I usually fire up Fiddler.

I find myself using all of these interchangeably when I explore new parts of the API, or in other ways have gone into "research mode". The utilities are for the most part self-explanatory, but I'll run through them nonetheless to point out things you don't notice at first glance.

Both GraphExplorer versions have a demo tenant you can use (not the same one), which is very useful when you just want to browse the general structure, and see some examples without caring about it being your actual data. However, the data exposed in v1 and v2 may not be the same.

Version 1 uses the Azure AD Graph API on the back-end to query the directory. Version 2 uses the Microsoft Graph API on the back-end. Sure, most of the data will match up, but it goes through a different layer of abstraction on its way back to you.

Let's say I for some reason need to list the servicePrincipals registered in my tenant, and figure out which organization the appId is registered in to differentiate between my internal apps, and those created by others. So, I head to the v2 GraphExplorer just to see if I can find an attribute for it, and use it in my code.

[caption id="attachment_3555" align="alignnone" width="573"] GraphExplorer servicePrincipal object[/caption]

That "appOwnerOrganizationId" attribute seems like the right one to hit. Type that in your code, execute a call, and boom - you get a JSON parsing error! You double-check that you typed it correctly. Makes no sense. Oh, wait, you're not executing your calls against the same Graph API…

Visit the v1 GraphExplorer , and see what the servicePrincipal object looks like there:

[caption id="attachment_3565" align="alignnone" width="455"] GraphExplorer v1 servicePrincipal object[/caption]

Notice what the attribute is called here? "appOwnerTenantId" refers to the same key value, (well, not in the screenshots because they are different apps), but with a different key name!
Pro tip: Always keep track of which Graph endpoint you are calling, and check the JSON structures accordingly, either by using the corresponding GraphExplorer, or the endpoint specific documentation.

Version 1 - Azure AD Graph API reference: https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/api-catalog
Version 2 - Overview of Microsoft Graph: https://graph.microsoft.io/en-us/docs

There are times where you want to use v1, and there are times when you want to use v2. You can use both in your app of course, but have a clear strategy for separating them.

Why are there two endpoints, and why are they not called v1 and v2 (even though I'm using version numbers to keep the UIs apart)?

The Azure AD Graph is, as implied, all about Active Directory objects. This would be users, groups, apps, etc. The Microsoft Graph is, in marketing jargon, "so much more". The new Graph collects, and exposes, more services than Azure AD. You can reach files in OneDrive, you can send mails through Exchange, etc. The vision is to basically expose all Microsoft API-based services through a common Graph API over time. (There is unsurprisingly a migration effort required to achieve this for some services.) So for future proofing you should in general strive to use the new API.

Not all functionality is there yet, so you may have to stick to the old API for some tasks. If it doesn't seem to be available in the new graph, and you're feeling comfortable with the preview concept, I would encourage you to see if it is available under the /beta branch. For instance this is what I had to use to do a GET on the servicePrincipals object.

You will possibly also notice that another notable difference between the two explorers is that v1 only supports GET, whereas you can do POST and PATCH as well in v2. Which is nifty if you want to either push content into AAD, or change what is already there. But what if you want to POST to the AAD Graph? Well, if I happen to have some test app running in Visual Studio I might just throw in a line or two of code. But if I want something quick and dirty I often turn to Fiddler. Since you probably don't want to go through an OAuth-login-dance in Fiddler the easy thing is to start it up, make sure it's capturing, login to the GraphExplorer , and copy the token from the captured traffic:

[caption id="attachment_3575" align="alignnone" width="473"] Token Capture in Fiddler[/caption]

Then you can just throw it into a new request, and play around before moving into "proper" code:

[caption id="attachment_3585" align="alignnone" width="485"] Fiddler Request Body[/caption]

This isn't exactly an advanced trick, but useful to include for those who haven't stumbled through it, possibly expecting the GraphExplorer to do some mumbo-jumbo preventing you from doing things like that. (If you use the demo tenant it seems they are doing things to prevent you from seeing the token.)

Wait a minute. I tried this, and it doesn't work as advertised. I signed in to the v2 explorer, grabbed the token, executed a query against /me, then I wanted some data from the v1 graph and I get a 401. But I have a valid token.

Yes, you have a valid token for the v2 Graph; not the v1 Graph. This is expected behavior though, and how access tokens generally work. You get a token that is valid for a specific resource - not a carte blanche to access everything. This isn't surprising if you have been working with OAuth before, but it still threw me off the first time because it didn't immediately occur to me that this mattered. This info is encoded in the token, but I'm not going to derail this train of thought with token-decoding just yet.
Pro tip: A token issued for one of the Graph endpoints will by default not work for accessing the other endpoint.

Single- and multi-tenancy

What more can you do with the GraphExplorers. Let me see… If you live in the single-tenant world you are probably happy with what you have in your own directory. But there are cases where you want to poke around in multiple tenants. This doesn't have to be due to creating multi-tenant apps, although that certainly is a valid scenario, but could easily be something like having a developer tenant and a production tenant. Since the developer tenant shouldn't contain critical stuff it's easier to use your production credentials for sign-in, and add that user as an admin in the dev tenant. This way you can switch between them in the portal to do stuff without logging out and back in all the time. (You could of course work with different browsers/private mode/incognito to have several logins active.)

By default the GraphExplorers will use the "home tenant". If you sign is as andreas@contoso.onmicrosoft.com , the contoso.onmicrosoft.com is the tenant it will look into. What if you want to work with northwind.onmicrosoft.com ? In the v1 GraphExplorer it's easy - the tenant is part of the query string - just change it to whatever you like (permissions will of course prevent you from unauthorized requests):

[caption id="attachment_3595" align="alignnone" width="415"] GraphExplorer v1 tenant[/caption]

This trick does unfortunately not work with the v2 GraphExplorer . Here the tenant is derived from the access token you present, and this is what will be used. This is not a limitation of the GraphExplorer , but the Microsoft Graph. You can include the tenant id in the query, and the query should go through, but not across tenants so it doesn't really help you if that's what you're trying to do. Such is life for now.

The Graph versus "integrating with Azure AD"

A common misconception that I think we should possibly clear up now that we've covered some of the things you can do, is what we mean by integrating with Azure AD. Because it's tiresome to explain everything in detail when talking about AAD we, (or at least I do), often use the word "integration" in ambiguous ways when referring to applications that talk to Azure AD in some way. But using the Graph, and using Azure AD is not necessarily the same thing.

Authentication (AuthN) and authorization (AuthZ) are handled through the auth endpoint; login.microsoftonline.com. (If you're using login.windows.net you should update your urls, since this is an old endpoint.) There is both a tenant-specific way to address the endpoint, and a generic one. Basically, if you know the tenant the users belong to you can use that, but for most cases it's better to go with /common . We'll cover this in greater detail in the future - this is a minor detail for now.

The Graph endpoints are of course related to Azure AD, but they're not the same. You should not refer to the auth endpoint as the Graph endpoint, and vice versa. For SSO-purposes in your app you may be more than happy to have the user authenticate with AAD, and you doing the authorization based on what the token contains. You might not need to even touch the Graph endpoints.

For other apps; for instance where you have a server back-end that assigns apps/services/tasks/something to end-users based on Groups in AAD you may care less about the SSO-bits in your app, but need to extract this info from the Graph. You would still need to go through the auth-dance, as that is an unavoidable part of getting access to data, but if you go with the client credentials flow this is less work than building mobile apps with sign-in.
Pro tip: Make sure what you define as "integration" isn't too far off with what whoever you are talking to defines as integration.

I think I'll call it a day for this post, but this has hopefully provided you with more things to keep in the back of your mind while hacking around with Azure Active Directory. More tips and tricks are in production :)
Version history
Last update:
‎Feb 12 2019 02:33 PM
Updated by: