Cross-tenant workload identities with a single secret

TL;DR – You can have cross-tenant workload identities authenticating using the secret or certificate from their home tenant.

File this one under ‘you learn something new every day‘. I always thought that since application registrations are global and service principals are local, that any multi-tenant application would have to authenticate locally. The documentation describes a multi-tenant applications as those with an audience of “accounts in any Azure Active Directory“, which makes perfect sense for the typical multi-tenant interactive application that allows end-users to access applications in their home tenant, where they also authenticate.

Well, it turns out, multi-tenant also means an application ID can authenticate in another tenant (tenant B) with the credentials that were originally created in the home tenant (tenant A). This is useful for background services or daemon processes applications that require application permissions (as opposed to delegated permissions). See my previous blog on this subject.

Register the application in tenant A

For example, I create an application, creatively named ‘MultiTenantApp’, in tenant A (Contoso).

I then add some permissions. In this case I am just testing to verify the domains in the tenant, using the domains endpoint, since that will later confirm I am connected to the right tenant. So, I am using Domain.Read.All.

And then I add a secret to this application, which will only ever exist in Tenant A (Contoso).

So, to verify I can login using the app-id via the CLI command.

az login --service-principal -u <app-id> -p <password-or-cert> --tenant <tenant>

And I can list the domains as shown below. I just want to verify I am connected to the correct tenant, which for now it’s the domain on the tenant A (Contoso).

Create the service principal on tenant B

So, now to create the service principal (without any secrets) in tenant B (PowerPuff), I use the browser to navigate to:

https://login.microsoftonline.com/common/adminconsent?client_id=<app-id> 

I am logging in as the Global Administrator, so I can consent to the permissions, as shown below:

I then verify the service principal (Enterprise Applications) is created with the correct permissions, since I consented as the Global Administrator above.

The step above is only done once, because I just need to create the service principal and consent to the permissions in tenant B (PowerPuff) one time.

Now I can test

I login with the app-id and the secret that was created in tenant A (Contoso), but I will access tenant B (PowerPuff).

And it works! I can authenticate with the app-id and secret from Contoso, as long as the Service Principal exists on any other tenant. This means I don’t need to keep secrets for each and every tenant that I need to access to run this background application.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: