Search code examples
c#azure-active-directorysingle-sign-onazure-app-registration

Authenticate AAD with multiple tenants


I have a dotnet 7.0 application (web app) and I want to be able to authenticate users via SSO from any Azure AD tenant. After authentication at Azure, I want to see the user's email-address and/or some kind of unique user id.

I have created a new App Registration in the Azure portal, under Azure Active Directory. The App registration is associated with my MPN account with a publisher. And I have tried using both Supported account types: 'Multitenant' and 'Any Microsoft Account'.

I can successfully authenticate users from my own tenant. But when a user tries to authenticate with a foreign tenant, Azure throws an error to the user: AADSTS50020: User account '[email protected]' from identity provider 'https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/' does not exist in tenant 'mydomain.com' and cannot access the application 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'(myapp) in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.

But I don't want to add users as external users in my own tenant, because I don't know all the users yet, and there will be too many. How can I get my application to authenticate users from foreign domains as well?

Program.cs:

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect; // nuget: Microsoft.Identity.Web
using Microsoft.AspNetCore.Authorization;
using Microsoft.Identity.Web; // nuget: Microsoft.Identity.Web
using System.Security.Claims;

var builder = WebApplication.CreateBuilder(args);
var authenticationBuilder = builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme);
authenticationBuilder.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.MapGet("/", (ClaimsPrincipal user, HttpResponse response) => 
{
    response.ContentType = "text/html";
    if (user.Identity?.IsAuthenticated ?? false)
        return $"Hello {user.GetDisplayName()}. <a href='/logout'>Logout</a>.";
    else
        return $"Hello. You are not authenticated. Please <a href='login'>log in</a>.";
});
app.MapGet("/logout", async context =>
{
    await context.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
    await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
});
app.MapGet("/login", [Authorize] (ClaimsPrincipal user, HttpResponse response) => response.Redirect("/"));
app.UseRouting();
app.UseAuthorization();
app.Run();

appsettings.json with values taken from the App registration in Azure AD:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "mydomain.com",
    "ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "TenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "CallbackPath": "/signin-oidc"
  },
  "AllowedHosts": "*"
}

Solution

  • To authenticate multiple tenants, create an Azure AD Application by selecting "Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant)":

    enter image description here

    For sample, I used below authorize endpoint to authenticate Multitenant users:

    https://login.microsoftonline.com/TenantID/oauth2/v2.0/authorize?
    &client_id=ClientID
    &response_type=code
    &redirect_uri=https://jwt.ms
    &response_mode=query
    &scope=https://graph.microsoft.com/.default
    &state=12345
    

    When I tried to authenticate other tenant user, I got the same error as below:

    enter image description here

    The error usually occurs, if the Azure AD Application is not configured as Multitenant or if you are passing the wrong sign-in URL to authenticate other tenant users.

    Note that: To authenticate multiple tenant users, you have to create Multitenant application and pass Sign-in URL as https://login.microsoftonline.com/organizations or need to pass organizations as value for the tenant id.

    Hence to resolve the error, I modified the authorize endpoint:

    https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?
    &client_id=ClientID
    &response_type=code
    &redirect_uri=https://jwt.ms
    &response_mode=query
    &scope=https://graph.microsoft.com/.default
    &state=12345
    

    The other tenant user is able to authenticate successfully:

    enter image description here

    enter image description here

    To resolve the issue, modify the appsettings.json file by passing organizations for TenantID :

    {
      "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "Domain": "mydomain.com",
        "ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "TenantId": "organizations",
        "CallbackPath": "/signin-oidc"
      },
      "AllowedHosts": "*"
    }
    

    I am able to generate the access token via Postman by using below parameters:

    https://login.microsoftonline.com/organizations/oauth2/v2.0/token
    
    client_id:ClientID
    scope:https://graph.microsoft.com/.default
    grant_type:authorization_code
    redirect_uri:https://jwt.ms
    code:code
    client_secret:ClientSecret
    

    enter image description here

    Reference:

    Error AADSTS50020 - User account from identity provider does not exist in tenant - Active Directory