My last post about Azure AD was about enabling single sign-on by letting your customers provision your application into their Azure AD tenant. SSO is important to make the end user login experience seamless. Who likes to put in credentials all the time.
As a service provider, you have other interests as well. Quite importantly, you may want to charge for the service your offering. How do you do that when you allow user provisioning in your customers' tenants? You can't simply query your own identity store for how many users are registered because you allowed your customers to administer access in their directory.
Fortunately, we have the Consent Framework when we allow a customer to provision an application into their tenant. The customers administrator has to agree to the level of access that the application will have to their directory. In the SSO scenario, the application only needs access to user profiles in the directory to authenticate and read user profile information.
We can, however, request additional permissions when the app is provisioned to gain access to data that will allow us to report on users with access to the application in each tenant.
First, we configure the application to require Directory Read Access.
Now when an administrator provisions the application, it requires consent for read access to the directory in order to get provisioned.
Now that we have consent to access to the directory we can query the directory with the Graph API. Let's see how that works.
First, we find the application's ServicePrincipal in the directory. The ServicePrincipal represents the application in the directory and is the entity to which users access grants are assigned to.
Details about the ServicePrincipal on Vittorio's blog.
Note that the ServicePrincipal in the customer's directory kept the same displayName and that the appId is the Client ID from the directory where the application was originally published.
With that knowledge, we can query the graph for the ServicePrincipal, for example with code like this:
ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(serviceRoot,
() => AuthenticationHelper.GetTokenFromRefreshTokenAsync(
var principals = activeDirectoryClient.ServicePrincipals
.Where(principal => principal.AppId.Equals("59f88d84-651c-4444-b33c-c587f6812b8f"))
The ActiveDirectoryClient class comes from the Active Directory Graph Client Library.
From the ServicePrincipal we can query the appRoleAssignedTo navigation property to get the users that are assigned access to that app.
var sp = principals.FirstOrDefault();
var userAssignments = (sp as IServicePrincipalFetcher).AppRoleAssignedTo.ExecuteAsync().Result;
It's worth pointing out that in order to get the AppRoleAssignments, we have to query via an IServicePrincipalFetcher. The IPagedCollection of AppRoleAssignment property sp.AppRoleAssignedTo is empty when you access it from the ServicePrincipal directly.
If we're putting all this together, we can issue Graph API queries to all tenants that provisioned the application to build a report on authorized users in each of those tenants. I've built a little page to show me the users from various tenants that have access to my application.
Btw., the same pattern with the Fetcher also applies to other navigation properties, e.g. in order to get the oauth2PermissionGrants, you'd again query using an IServicePrincipalFetcher:
var fetcher = sp as IServicePrincipalFetcher;
IPagedCollection<IOAuth2PermissionGrant> grants = fetcher.Oauth2PermissionGrants.ExecuteAsync().Result;
Now you can query and report on the users in tenants that use your applications without having to build your own tracking system. That's quite essential when you're looking to bill for your service.