Azure AD身份验证 – 使用组织令牌调用Web API(多租户)失败。

huangapple go评论96阅读模式
英文:

Azure AD auth - calling web api (multi-tenant) with organizations token fails

问题

I can provide a summary of your request in Chinese:

我有一个ASP.NET Core Web应用程序,调用一个ASP.NET Core Web API,并使用Azure AD和Microsoft.Identity.Web。它们在Azure AD中有不同的应用程序注册,并且都已正确配置(应用程序注册相互了解,Web应用程序还请求访问Web API等)。

这是一个多租户应用程序。Web应用程序(前端)可以被多个租户使用。只有Web应用程序调用Web API(后端),但它还需要支持多个租户,因为我们为每个租户都有一个数据库。

我想要使用"organizations"方法而不是"common"方法,因为此应用程序应仅供其他企业使用。个人账户的用户不应能够登录,这似乎是"common"方法的用途。

有趣的是,当我尝试使用我的个人帐户登录时,出现错误提示不允许登录。可能是因为我如何配置Azure AD应用程序注册的原因?

Web应用程序配置如下:

services
    .AddMicrosoftIdentityWebAppAuthentication(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi(Configuration.GetValue<string>("Scopes").Split(" "))
    .AddDistributedTokenCaches();

Web API配置如下:

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
        };
    });

问题是,当我使用"common"时,整个设置完美运行,但当我使用"organizations"时,出现以下错误。

如何在使用Azure AD应用程序注册的ASP.NET Core Web API中添加多租户支持(同时仍然能够限制为特定租户)?

英文:

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&lt;string&gt;(&quot;Scopes&quot;).Split(&quot; &quot;))
    .AddDistributedTokenCaches();

----
Configuration:

  &quot;AzureAd&quot;: {
    &quot;Instance&quot;: &quot;https://login.microsoftonline.com/&quot;,
    &quot;TenantId&quot;: &quot;organizations&quot;,
    &quot;ClientId&quot;: &quot;MY_CLIENT_ID&quot;,
    &quot;CallbackPath&quot;: &quot;/signin-oidc&quot;,
    &quot;SignedOutCallbackPath &quot;: &quot;/signout-callback-oidc&quot;,
    &quot;ClientCertificates&quot;: [
      {
        &quot;SourceType&quot;: &quot;KeyVault&quot;,
        &quot;KeyVaultUrl&quot;: &quot;KEYVAULT_URL&quot;,
        &quot;KeyVaultCertificateName&quot;: &quot;AzureActiveDirectoryAppCert&quot;
      }
    ]
  },

  &quot;Scopes&quot;: &quot;https://companyname.com/webapi/Api.Access&quot;,

When I call my API, I get a token like this and then call the API:

var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService&lt;ITokenAcquisition&gt;();

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 =&gt;
    {
        options.Audience = &quot;https://companyname.com/webapi;
        options.Authority = &quot;https://login.microsoftonline.com/organizations&quot;;
        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: &#39;https://login.microsoftonline.com/organizations/.well-known/openid-configuration&#39;.

---&gt; System.IO.IOException: IDX20807: Unable to retrieve document from: &#39;https://login.microsoftonline.com/organizations/.well-known/openid-configuration&#39;. HttpResponseMessage: &#39;StatusCode: 400, ReasonPhrase: &#39;Bad Request&#39;, Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent

Some more error details: {&quot;error&quot;:&quot;invalid_tenant&quot;,&quot;error_description&quot;:&quot;AADSTS90002: Tenant &#39;organizations&#39; not found. Check to make sure you have the correct tenant ID and are signing into the correct cloud...&quot;}

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?

答案1

得分: 1

当我使用组织端点时,我遇到了相同的错误。

appsetting.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "testthetenant365.onmicrosoft.com",
    "ClientId": "50xxxx06e",
    "TenantId": "Organizations",
    "ClientSecret": "ZHxxxbGh",
    "CallbackPath": "/signin-oidc"
  },
  "DownstreamApi": {
    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "https://graph.microsoft.com/.default"
  }
}

错误:

System.InvalidOperationException: IDX20803: 无法从以下位置获取配置:'https://login.microsoftonline.com/Organizations/xxx/v2.0/.well-known/openid-configuration'。
 ---&gt; System.IO.IOException: IDX20807: 无法从以下位置检索文档:'https://login.microsoftonline.com/Organizations/xxx/v2.0/.well-known/openid-configuration'。HttpResponseMessage: 'StatusCode: 404, ReasonPhrase: 'Not Found',Version: 1.1,Content: System.Net.Http.HttpConnectionResponseContent,Headers:

注意: /common 端点支持个人帐户,但 /organizations 仅支持工作或学校帐户。

然后我检查并更改了我注册应用程序的支持帐户类型:

然后它要求管理员同意访问端点。
注意:我登录的帐户是工作和学校帐户

在我的应用注册清单中,我有 "accessTokenAcceptedVersion": 2

确保用户登录的租户被应用程序允许,并已被授予 API 权限的管理员同意。

并检查受众部分 Client application configuration (MSAL) - Microsoft Entra | Microsoft Learn

在权限已被授予并且使用上述配置时,端点可以工作:

并且作为我调用 /.default 的 graph 端点的范围。
范围:https://graph.microsoft.com/.default.

对于您的 API,请检查范围是否必须授予其他权限 api://<clientId>/.default.

或者,如果您知道要允许的租户的租户 ID,可以进行验证。
Startup.cs

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = "https://login.microsoftonline.com/common";
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuers = new[] { "https://login.microsoftonline.com/TENANT_ID1/v2.0", "https://login.microsoftonline.com/TENANT_ID2/v2.0" },
            //token validation parameters...
        };
    });

查看 将单租户应用程序转换为多租户 Azure AD - Microsoft Entra | Microsoft Learn

英文:

When I used the organizations endpoint , I was getting the same error.

appsetting.json

{
  &quot;AzureAd&quot;: {
    &quot;Instance&quot;: &quot;https://login.microsoftonline.com/&quot;,
    &quot;Domain&quot;: &quot;testthetenant365.onmicrosoft.com&quot;,
    &quot;ClientId&quot;: &quot;50xxxx06e&quot;,
    &quot;TenantId&quot;: &quot;Organizations&quot;,
    &quot;ClientSecret&quot;: &quot;ZHxxxbGh&quot;,
    //Audience&quot;: &quot;50xxx06e&quot;,
    &quot;CallbackPath&quot;: &quot;/signin-oidc&quot;
  },
  &quot;DownstreamApi&quot;: {
    /*
     &#39;Scopes&#39; contains space separated scopes of the Web API you want to call. This can be:
      - a scope for a V2 application (for instance api:xx/access_as_user)
      - a scope corresponding to a V1 application (for instance &lt;App ID URI&gt;/.default, where  &lt;App ID URI&gt; is the
        App ID URI of a legacy v1 Web application
        App ID URI of a legacy v1 Web application
      Applications are registered in the https:portal.azure.com portal.
    */
    &quot;BaseUrl&quot;: &quot;https://graph.microsoft.com/v1.0&quot;,
    //&quot;Scopes&quot;: &quot;https://graph.microsoft.com/User.Read&quot;
    //&quot;Scopes&quot;: &quot;api://xxxx/access_as_user&quot;
     &quot;Scopes&quot;: &quot;https://graph.microsoft.com/.default&quot;

  },

Error:

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: &#39;https://login.microsoftonline.com/Organizations/xxx/v2.0/.well-known/openid-configuration&#39;.
 ---&gt; System.IO.IOException: IDX20807: Unable to retrieve document from: &#39;https://login.microsoftonline.com/Organizations/xxx/v2.0/.well-known/openid-configuration&#39;. HttpResponseMessage: &#39;StatusCode: 404, ReasonPhrase: &#39;Not Found&#39;, Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:

Azure AD身份验证 – 使用组织令牌调用Web API(多租户)失败。

> Note: /common endpoints supports personal accounts but /organizatioms support only work or school accounts.

Then I checked and changed the support account type of my registered application:

Azure AD身份验证 – 使用组织令牌调用Web API(多租户)失败。

Then it asked for admin consent to access the endpoint.
Note: The account with which I logged in was work and school account

Azure AD身份验证 – 使用组织令牌调用Web API(多租户)失败。

I have &quot;accessTokenAcceptedVersion&quot;: 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:

Azure AD身份验证 – 使用组织令牌调用Web API(多租户)失败。

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://&lt;clientId&gt;/.default.

Azure AD身份验证 – 使用组织令牌调用Web API(多租户)失败。

Alternatively , if you know the tenant Id’s of tenants to be allowed , they can be validated.
Startup.cs

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =&gt;
    {
        options.Authority = &quot;https://login.microsoftonline.com/common&quot;;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuers = new[] { &quot;https://login.microsoftonline.com/TENANT_ID1/v2.0&quot;, &quot;https://login.microsoftonline.com/TENANT_ID2/v2.0&quot; },
            //token validation parameters...
        };
    });

See Convert single-tenant app to multi-tenant on Azure AD - Microsoft Entra | Microsoft Learn

huangapple
  • 本文由 发表于 2023年6月30日 01:20:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76583294.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定