The easiest way to illustrate the purpose of this blog is to describe the scenario we are trying to solve:
‘ContosoApps’, a Microsoft cloud solution provider (CSP), sells Office 365 and additionally bundles their cloud software and services (‘family-of-apps’) to provide value-add to their customers. As part of the customer acquisition flow, the goal is for a new customer to sign up for Office 365 (which includes creating a new tenant and subscription) through ContosoApps. Additionally, as part of this onboarding process the flow should “pre-install” ContosoApps’ ‘family-of-apps’ so that all the customer’s users can take advantage of.
Today this ‘family-of-apps’ onboarding (through the CSP pre-consent flow in Microsoft Graph) only works for applications that access Directory and Intune functionality. If the app tries to access other services behind Microsoft Graph, this pre-consent flow will not work.
This inability to use the CSP pre-consent flow then requires an admin of the customer to pre-consent each AAD application in the ‘family-of-apps’ manually by opening the application, signing-in and then consenting (accepting) the consent dialog describing the permissions required.
This manual approach is sometimes considered laborious and often leads to a bad user experience which can lead to a negative perception to your ‘family-of-apps’
Therefore, the objective of this blog is to provide guidance on how to use the AAD Graph to allow a tenant (customer / ISV user) admin to grant pre-consent for multiple applications (‘family-of-apps’) by consenting to a single ‘bootstrapper’ application.
That is, how you as an ISV / developer, can create a bootstrap application that you can then use to onboard your AAD applications to your customers / users preventing the tenant admin to have to do multiple consents. i.e. one for each of your AAD applications or ‘family-of-apps’.
The approach requires that there is a ‘bootstrap’ application that, once granted the appropriate permissions by an administrator, can record consent grants for the family-of-apps. If you as an ISV / developer also happens to be a CSP as well, then the ‘bootstrap’ application can actually be pre-consented following the how-to-set-up-a-partner-managed-application flow in this document. If you are not a CSP or you prefer to manually configure the bootstrap application, you should skip the steps under ‘Pre-consent your app for all your customers’.
Important: When registering the bootstrap application in the Azure Portal in your organisation’s directory, you should configure the application to require ‘Access the directory as the signed-in user’ in the API Windows Azure Active Directory as per figure below. You also need to add a permission for the Microsoft Graph API, e.g. ‘Sign in and read user profile’, this ensures the necessary Service Principal is created for the customer’s tenant directory.
Note: It is also assumed that each of your applications (‘family-of-apps’) are already registered with AAD through either the Application Registration experience in the Azure Portal, or via the Application Registration website that can be found here.
Note: If you plan to create a web app version of the bootstrap application, remember to register it as multi-tenant.
To help you understand the steps required to build the bootstrap application, we have included two applications you can download and modify. Once registered in your tenant’s directory (see above) and then modified to include your ‘family-of-apps’, the code should work as-is. However, how you onboard your customer’s will probably require you to consider where the bootstrap application fits in your onboarding process. Therefore, at the least you should perhaps consider the downloadable applications as simply templates for your own bootstrap application that you can use to understand how to build your own.
For this blog, we are going to concentrate on the code in the native .NET Console application.
Where possible (more on that later) we are using the AAD Graph .NET SDK, which is installed as NuGet package, to make the requests to the AAD Graph. Whilst it is possible to make requests directly against the AAD Graph rest endpoint (graph.windows.net) using the .NET SDK simplifies the code and removes the need for us to serialize and de-serialize JSON objects.
There is also a reference to the Active Directory Authentication Library or ADAL for short. Using this library simplifies the authentication process immensely, easily allowing us to separate the authentication code from the application logic. All the code required to authenticate a user can be found in the class AuthenticationHelper.cs
Finally, there is a reference to the Microsoft Graph Service Client SDK. Whilst the bootstrap application does not make use of the data returned by the call there is a circumstance where a need to make a request is required…more on that later.
The bootstrap application (once granted the correct permissions) will be able to programmatically provision any AAD application, including providing consent (administrative consent on behalf of the organisation) if it is run in the context of a signed-in administrator in the target customer / user tenant.
The following sections provide details on how to record consent for delegated permissions (i.e. for interactive apps that run in the context of a signed-in user) and application permissions (i.e. for daemon or background services that run without any signed-in user being present). See this article for more details. The process of provisioning and recording consent will need to be done for each of the apps in the ‘family-of-apps’ that you provide.
Configuration: Once you have registered the bootstrap application there are a number of parameters that you need to modify in order for the authentication to happen successfully. These parameters can all be found in the class Constants.cs. The parameters you need to modify are:
- BootstrapClientId – generated when registering the application in the Azure Portal. This value is represented by the Application Id for the application.
- RedirectUrl – specified when registering the application in the Azure Portal.
Authentication: As per previous comments, the logic to Authenticate a user is in the most the responsibility of the AuthenticationHelper.cs class. It’s only purpose is to authenticate a user and manage the access token. There are 2 tokens, one the for the AAD resource and one for the Microsoft Graph resource. Once the user has authenticated we cache the access token as a static resource for the lifetime of the process. This effectively means the user only needs to sign-in once (maybe twice if we do need to use the Microsoft Graph resource) and then we can make use of that token for all future requests.
Consent: The code for processing the consent flow can all be found in the class Request.cs.
When adding the OAuthGrant permissions you need to have at hand the following values for each of the applications in your ‘family-of-apps’:
- AppId…this is the AppId of your AAD application
- DisplayName…this is the name you have given to your AAD application
- ResourceServicePrincipalId…this is the Id relevant to the API the permission belongs to, e.g. if you need to add the permission User.Read for the Microsoft Graph API then you will need the Id of the Microsoft Graph API…values for the Microsoft Graph API and the AAD Graph API can be found in the class Constants.cs
- DelegatedPermissions…represented as a string delimited by a <space>, these are the delegated permissions required by your AAD application, e.g. if you require to read the user’s profile and send an email on behalf of the user, you will need the following scope of permissions “User.Read Mail.Send”. Note, if the permissions cross multiple APIs, then you need to create am OAuthGrant per API.
- AppOnlyPermissions…represented by a list of strings, these are the app-only permissions required by your AAD applications. Note, these permissions are represented by their GUID value and not their string name. To find the GUID value have a look at the AAD Application manifest file under resources.
The assumption we have made in the Bootstrap application is that the application permissions you need to the user to consent belong to either the Microsoft Graph API or the AAD Graph API. Prior to consenting to these permissions, the Microsoft Graph and/or AD Graph API applications need to be represented as a Service Principal in the target tenant. At the time of writing, it is not possible to add the Microsoft Graph API application as a Service Principal directly in code. However, the Service Principal for each API will be added JIT to your tenant once consent to any application requesting permissions using those APIs (e.g. the AD Graph or Microsoft Graph). Therefore, your bootstrap application should include whatever basic ‘Read own profile’ permission is available to ensure the SPs to the Microsoft APIs are automatically created. The console application then will be able to request consent for use of the bootstrap application; it will prompt the user to sign-in again with their credentials as a new access token needs to be generated to make the request.
The next step is to add any other API applications as Service Principals that your AAD applications needs to consent permissions for. As per previous comments, we assume you will only need permissions for the Microsoft Graph API and the AAD Graph API and therefore these are the only Service Principals we add.
The code to add the Service Principal will only add if the tenant does not already have the Service Principal in their directory.
If you need to add more, then follow the code on how to create the Service Principal replacing the GUID and the Display name for each. Note, if you are struggling to find the GUID for the API then the advice is to look in the manifest file associated with your AAD application as per the app-only permission Ids discussed earlier.
Next, create a collection OAuthGrants. The contents of each OAuthGrant and the values you need was discussed earlier…the code to do so is as per below:
From here on in you should no longer have to modify any more of the code. The process to add the permissions is as follows:
You will notice when adding the App-only permissions we don’t use the AAD Graph Client SDK. This is because at the time of writing the bootstrap application, the SDK does not support adding AppRoleAssignments.
Okay we are done. The bootstrap application should now have granted all the necessary permissions for your AAD applications (‘family-of-apps’) require. You should find now that when a user of the tenant, targeted by the bootstrap application, sign-ins in to your AAD application the consent dialog should be suppressed.
Remember, you can download either a native or a web application bootstrap here.
If you would like to know more about the specific API calls used for programmatic consent (e.g. for use in a language unsupported by the Graph SDK), see also this post by Arsen which details some of the API calls and their parameters in greater detail. You can also use HTTP tracing tools like Fiddler to view the API calls made by this code.
Finally, thank you to Stewart Adam and Denis Kisselev for collaborating on this project.