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.