Using Azure Multi-Tenant App Registrations

Azure Identity4 min read

Understanding Azure multi-tenant app registrations for cross-tenant access scenarios, enabling applications to interact with resources across different Azure AD tenants.

Using Azure Multi-Tenant App Registrations

App Registrations in Azure are the key to accessing resources in both Azure and Office 365 programmatically, but yet I find they are often confusing and misunderstood by so many! In the last few days, I've fielded questions from both teammates and customers alike where there was a requirement for an app in one tenant to be able to retrieve information about another tenant.

Taking a step back, why do we need an App Registration? App Registrations are a component of the Microsoft identity platform and Identity and Access Management (IAM). Whether it's a client application like a web or mobile app, or it's a web API that backs a client app, registering it establishes a trust relationship between your application and the identity provider, the Microsoft identity platform.

Using Microsoft's Graph API as an example, there are two ways app registrations can interact with the Graph API:

  • Delegated permissions: apps that have a signed-in user present
  • Application permissions: apps that run without a signed-in user present

But what if we need to access data from an external tenant? That's where multi-tenant App Registrations come in. A multi-tenant application is basically a way for any Azure AD tenant to use your application, by creating passwordless trusts between the tenants, which ultimately enable your application to get and interact with data from the external tenants.

Multi-tenant App Registration Setup

Image: Microsoft Documentation - Convert app to multi-tenant

Note: These next steps assume you have some level of experience with creating an App Registration, configuring platform URLs and creating secrets. If not, read through the quickstart to get up to speed.

Setting Up Multi-Tenant App Registrations

So how do you set up a multi-tenant app in Azure? As a developer, when creating an App Registration all you need to do is select one of the multi-tenant options.

Multi-tenant App Registration Options

Then in the case of delegated permissions for an API, when a user goes to authenticate to your app they'll be prompted to grant access to whichever scopes you've selected in your API permissions. But what if you have background workers which also need access to data in the external tenant? Delegated user permissions won't work here — this is where application permissions come in.

You'll first need to ensure your application has an "Application" permissions type selected instead of, or in addition to "Delegated" (in this case from the Graph API).

Application Permissions Configuration

Admin Consent Configuration

For any of your customers who will be using your app, they'll also need to enter in the admin consent URL into their browser for your app to be added to their Enterprise Applications within their tenant:

https://login.microsoftonline.com/organizations/v2.0/adminconsent?client_id={your-client-id}&scope=https://graph.microsoft.com/.default

Lastly, you'll need to get a copy of your customers' tenant ID for use programmatically when making calls to the Graph API.

Making API Calls to External Tenants

We're now ready to make an API call to get information from your customer's tenant! Using the steps from Microsoft's documentation, we first need to authenticate with Microsoft on behalf of your client's tenant:

POST https://login.microsoftonline.com/{your-clients-tenant}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id={your-app-registration-client-id}
&client_secret={your-app-registration-client-secret}
&scope=https://graph.microsoft.com/.default
&grant_type=client_credentials
&resource=https://graph.microsoft.com

This request should result in a successful response and an object which looks like the following:

{
  "token_type": "Bearer",
  "expires_in": "3599",
  "ext_expires_in": "3599",
  "expires_on": "1630420066",
  "not_before": "1630416166",
  "resource": "https://graph.microsoft.com",
  "access_token": "eyJ0eXAiOiJKV1QiLCJub2..."
}

Then using the access_token value from the result, you can now make a subsequent call to the Graph API by passing it in as a bearer token:

GET https://graph.microsoft.com/v1.0/users/
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub2...

This should result in a response that lists all the users from the external tenant — you can validate this by looking at the tenant ID in the @odata.id portion in the response:

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
  "value": [{
    "@odata.id": "https://graph.microsoft.com/v2/4...3f5/directoryObjects/f...407/Microsoft.DirectoryServices.User",
    "displayName": "Gavin Lewis",
    "givenName": "Gavin",
    "preferredLanguage": "en-AU",
    "surname": "Lewis",
    "userPrincipalName": "gavin@....onmicrosoft.com",
    "id": "f...407"
  }]
}

Conclusion

And there you have it! You're now able to retrieve information from external tenants by using multi-tenant App Registrations!