Tuesday 5 January 2021

Microsoft 365 multi-tenant apps: Working with application permissions in Microsoft Graph

Creating multi-tenant (SaaS) apps in Microsoft 365 has been possible for a while now. Azure AD multi tenant apps allow us to host our custom applications in an Azure AD/M365 "home" tenant while enabling the apps to also have access to resources hosted in other tenants. To know more about multi-tenant apps, head over to the Microsoft docs: https://docs.microsoft.com/en-in/azure/active-directory/develop/single-and-multi-tenant-apps

Hosting applications in a home tenant as SaaS has a lot of advantages particularly for ISVs when it comes to product based applications. Users are able to consume the apps directly by signing into them instead of the conventional way of an admin having to deploy the product to the customer tenant first. It makes life easy for the admins as well as they don't have to go through complex deployment scripts and instructions. Moreover, after the application is deployed, new features and bug fixes can be rolled out to the application "on the fly" as opposed to releasing feature packs and hotfixes which again have to be installed manually.

So in this post, we are going to have a look at using the Microsoft Graph API in such apps configured to be multi tenant.

(Multi tenant apps also allow users with personal Microsoft accounts to sign into them but that is a topic for another day! Also, in this post we will only focus on the application permissions i.e. granting permissions to applications without a user context)

Configure an app to be a multi-tenant in the home tenant's Azure AD

1) When creating a multitenant app registration, make sure that the "Accounts in any organizational directory" is selected. Also, we need to add a redirect url as this will be the url the admin will be redirected to after successfully granting consent to our application. Ideally, this would be the landing page of your application but in the screenshot I am just using the AAD home as an example:



2) Assign required permissions. In this case, we are going to demo the code to get all the Microsoft 365 Groups on the tenant and also the root SharePoint Online site, so selecting the relevant permissions here:



3) Create a client secret and record it along with the client id. We will need this later in our code.



Granting consent to a multi tenant app in other "consumer" tenant

Next, let's have a look at how the multi tenant app hosted in it's home tenant can be granted permission to access resources in other tenants. 

What we will have to do is to construct a url for admin consent which would be unique to our application. An Azure AD admin of the other tenant will need to navigate to the url and then consent to granting the permissions to our app on the tenant. The Azure AD url will have the following structure:

In the link above, replace the client id with the client id of your multi tenant Azure AD app. Also, notice that we are using the /.default static scope which means that all permissions configured in the app will be requested for consent. 

When the admin navigates to this url, they will see the consent prompt:


Once the consent is granted, the multitenant app will have permissions to access the resources on the other tenant. This can be checked by going to:

Azure Active Directory > Enterprise Applications > All applications and searching for our app there.


This confirms that the multi tenant app has permissions on this tenant. Also this process can be repeated on any number of Azure AD/M365 tenants.

Use the Microsoft Graph API to get Microsoft 365 data from the consumer tenant

With everything setup and also the admin consent granted, let's have a look at the Microsoft Graph code to get data from the consumer tenant.

In this code, I am using the .NET SDK for Microsoft Graph found on nuget here:

Microsoft.Graph

And the new preview version of Microsoft.Graph.Auth found here:

Microsoft.Graph.Auth

And finally here is the code to get all the Microsoft 365 Groups and the SharePoint root site url of the consumer tenant. For the sake of simplicity, I am using a .NET Core console application:

And we are able to get the data from the consumer tenant back:


Thanks for reading! Hope this helps.

No comments: