C# Microsoft Identity Framework multitenant application authenticate with guest accounts

68 Views Asked by At

I'm building a multitenant application that also needs to sign guest users (users added as guests, not anonymous). The guest must be able to access resources in the tenant. For example:

  • User X from Tenant A is a guest in Tenant B. Must be able to access resources in Tenant B
  • User Y is an account from an external provider. It is also a guest in Tenant B. Must be able to access resources in Tenant B
  • User Z is an account from an external provider. It is a guest in Tenant C. Must be able to access resources in Tenant C

Each user selects the tenant they want to interact with, so obtaining the tenantId is not an issue.

Microsoft Identity Framework really simplifies the configuration for the most common cases, but I can't find a way to configure the application with multitenant AND guest users.

My code is fairly standard:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(options =>
        {
            Configuration.Bind("AzureAd", options);
        }
        )

And in the controller

[HttpGet]
[AuthorizeForScopes(Scopes = new string[] { GraphScope.FilesReadAll })]
public async Task<IActionResult> Index(string driveId, string tenantId)
{
    var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { GraphScope.FilesReadAll }, tenantId: tenantId);
    //etc
}

I mainly followed the examples from here

Main problems:

  • [AuthorizeForScopes] uses static scopes, so it is impossible to use a scope from another tenant (can't do for example {tenantUrl}/.default)

  • I can't use the "common" authority (as in "https://login.microsoftonline.com/common") since I need users to get claims from a specific tenant.

I was able to use a flow similar the one for AuthorizeForScopes while obtaining the token. My idea was to return a ChallengeResult action with the specific authority, but I can't find information on how to configure it, or if that's even possible.

try
{
    var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync ...
}
catch (someAuthException)
{
    return ChallengeResult ...
}

Is there a way to do so, or is there a simpler way to accomplish what I try to do?

0

There are 0 best solutions below