I have an ASP.NET Core web app that calls an ASP.NET Core web api and I'm using Azure AD with Microsoft.Identity.Web . Both have different app registrations in Azure AD and both are configured correctly (Both app registrations now each other, the web app also requests access to the web api, etc..)
This is a multi-tenant application. The web app (front-end) can be used by multiple tenants. Only the web app calls the web-api (back-end), but it also needs to support multiple tenants because we have a database for each tenant.
I feel like I want to use the organizations approach and not the common approach because this application should only be used by other businesses. People with personal accounts should not be able to log in, which is (as far as I know) what common is for.
Funnily enough, when I try to log in using my personal account, I get an error about it not being allowed. Probably because of how I configured my Azure AD app registration?
Web app configuration
The web app is configured like this:
services
.AddMicrosoftIdentityWebAppAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi(Configuration.GetValue<string>("Scopes").Split(" "))
.AddDistributedTokenCaches();
----
Configuration:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "organizations",
"ClientId": "MY_CLIENT_ID",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath ": "/signout-callback-oidc",
"ClientCertificates": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "KEYVAULT_URL",
"KeyVaultCertificateName": "AzureActiveDirectoryAppCert"
}
]
},
"Scopes": "https://companyname.com/webapi/Api.Access",
When I call my API, I get a token like this and then call the API:
var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
// Token is sent successfully to the API
Web api configuration
The web api is configured like this:
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Audience = "https://companyname.com/webapi;
options.Authority = "https://login.microsoftonline.com/organizations";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false // TODO: Validate that only allowed tenants can access API
};
});
The problem
This entire setup works PERFECTLY when I use common, but when I use organizations I get the following error:
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://login.microsoftonline.com/organizations/.well-known/openid-configuration'.
---> System.IO.IOException: IDX20807: Unable to retrieve document from: 'https://login.microsoftonline.com/organizations/.well-known/openid-configuration'. HttpResponseMessage: 'StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent
Some more error details: {"error":"invalid_tenant","error_description":"AADSTS90002: Tenant 'organizations' not found. Check to make sure you have the correct tenant ID and are signing into the correct cloud..."}
I know that the common endpoint has valid openid-configuration whereas the organizations endpoint returns a 400, but I don't understand how I am then supposed to make this work.
I tried following an official sample (which uses services.AddMicrosoftIdentityWebApiAuthentication(Configuration)) but this also didn't work for the same reasons. Another SO post also looked promising but caused the same error.
How can I add multi-tenant support (whilst still being able to restrict it to specific tenants) in an ASP.NET Core web api that uses an Azure AD App registration?
When I used the organizations endpoint , I was getting the same error.
appsetting.json
Error:
Then I checked and changed the support account type of my registered application:
Then it asked for admin consent to access the endpoint. Note: The account with which I logged in was work and school account
I have
"accessTokenAcceptedVersion": 2, in the manifest of my App registration.Make sure the tenant with user is going to login is allowed by the application and granted admin consent to api permissions.z
And check on the audience part Client application configuration (MSAL) - Microsoft Entra | Microsoft Learn
With permissions granted and with above configuration, the endpoint worked:
And scope is for graph as I am calling grapph endpoint with
/.default. scope:https://graph.microsoft.com/.default.For your api : check scope if it has to be granted for other permissions
api://<clientId>/.default.Alternatively , if you know the tenant Id’s of tenants to be allowed , they can be validated. Startup.cs
See Convert single-tenant app to multi-tenant on Azure AD - Microsoft Entra | Microsoft Learn