Web api 的 AAD 客户端凭据流请求范围

发布于 2025-01-13 18:27:18 字数 2337 浏览 7 评论 0原文

我有一个控制台应用程序,需要支持两个流程,针对 AAD 进行身份验证以与 Web api 对话:

  • 对于人类的常规使用,它需要支持交互式登录,
  • 以供 CI/CD 管道使用,它需要支持客户端凭据。

交互流程工作完美,但客户端凭据流程给我带来了请求范围的问题。

我正在使用最新的 Microsoft.Identity* nuget 包。

当我像交互流那样构建 webapi 的范围时,我收到一条错误消息,告诉我对于客户端凭据流,我需要附加 ./default。好吧,公平地说,我还发现 文档为此,所以我附加 ./default。但是当我这样做时,我收到另一条错误消息告诉我

在名为 的租户中找不到名为 api:///access_as_user 的资源主体。

此错误消息有两个问题:

  • 引用的资源主体肯定存在 - 另外,如果不存在,我将无法交互式登录,但正如前面提到的,交互式登录工作得很好,
  • 它说 api://< webApiAppId>/access_as_user,而不是 api:///access_as_user/.default,尽管我附加了

我的下一个:嗯,也许问题是应用程序用于客户端凭据流的注册没有 web-api 的权限。但确实如此。

所以现在我已经没有想法了。希望这里有人可以提供帮助。

为了让一切变得更清晰,让我列出所涉及的应用程序注册:

A. Web Api

  • 是通过 VS Wizard/dotnet-msidentity 工具设置的
  • ,定义了一些应用程序角色,
  • 公开了单个 API api://;/access_as_user

B. 交互式登录

  • 创建
  • 重定向 URI
  • 手动为本地主机API 权限 :添加了 WebApi | access_as_user 作为委托

非交互式登录/服务主体

  • 设置
  • C. CI/CD 管道手动
  • 也可用于其他用途,具有 ClientSecret 定义的
  • API 权限:添加了 WebApi | access_as_user 。 access_as_user 为 A 定义了 2 个应用程序角色,
  • 具有与此处无关的其他 API 权限(对于图)
  • 授予管理员对所有权限的同意

我用于身份验证的代码是(对于机密流程):

ConfidentialClientApplicationBuilder.Create(_configuration.ApplicationId)
            .WithTenantId(_configuration.Directory)
            .WithLogging(Log, LogLevel.Error)
            .WithClientSecret(_configuration.ClientSecret)
            .Build()
            .AcquireTokenForClient(_configuration.Scopes)
            .ExecuteAsync();

其中 _configuration 的值为:

  • ApplicationId:应用注册中的 appId C
  • Directory:我的 AAD 租户的名称
  • ClientSecret:秘密来自应用程序注册 C
  • Scopesopenidprofileapi:///access_as_user/.default 的数组代码>

I got a console app that needs to support two flows, authenticating against AAD to talk to a web api:

  • for regular usage by humans, it needs to support interactive login
  • for usage by a CI/CD pipeline it needs to support client-credentials.

The interactive flow works perfectly, but the client-credentials flow is giving me problems with the requested scope.

I'm using the latest Microsoft.Identity* nuget packages.

When I construct the scope for the webapi like I do for the interactive flow, I get an error message telling me that for client-credentials flows I need to append ./default. Okay, fair enough, I also found documentation for this, so I append ./default. But when I do that, I get another error message telling me

The resource principal named api:///access_as_user was not found in the tenant named .

There are two problems with this error message:

  • the resource principal quoted definitely exists - also, I couldn't login interactively if it didn't, but as mentioned, interactive login works just fine
  • it says api://<webApiAppId>/access_as_user, not api://<webApiAppId>/access_as_user/.default, despite my appending that

My next though was: well, maybe the problem is that the app registration used for the client-credentials flow doesn't have permissions on the web-api. But it does.

So now I've run out of ideas. Hopefully, someone here can help.

To make everything a bit clearer, let me list the app regs involved:

A. Web Api

  • Was setup via the VS Wizard/dotnet-msidentity tool
  • has a few App Roles defined
  • exposes a single API api://<itsownAppId>/access_as_user

B. Interactive Login

  • manually created
  • redirect URI for localhost
  • API Permissions: added WebApi | access_as_user as delegated

C. Non-interactive login/Service Principal

  • setup manually
  • is used also for other things by the CI/CD pipeline
  • has a ClientSecret defined
  • API Permissions: added WebApi | access_as_user with 2 of the app roles defined for A
  • has other API Permissions that have nothing to do with this here (for Graph)
  • granted admin consent for all permissions

The code I use to authenticate is (for the confidential flow):

ConfidentialClientApplicationBuilder.Create(_configuration.ApplicationId)
            .WithTenantId(_configuration.Directory)
            .WithLogging(Log, LogLevel.Error)
            .WithClientSecret(_configuration.ClientSecret)
            .Build()
            .AcquireTokenForClient(_configuration.Scopes)
            .ExecuteAsync();

where the values of _configuration are:

  • ApplicationId: the appId from app registration C
  • Directory: the name of my AAD tenant
  • ClientSecret: the secret from app registration C
  • Scopes: array of openid, profile and api://<appIdOfWebApiFromC>/access_as_user/.default

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绿光 2025-01-20 18:27:18

因此,事实证明,附加 ./default 的文档不够清晰:您并不打算将其附加到作用域,而只是将其附加到“资源 id”。对于资源 ID,它们意味着“api://”部分权限名称。

因此,在您通常请求 api:///access_as_user 的地方,对于客户端凭据流程,您必须请求 api:///.default

So, it turns out that the documentation for appending ./default is not quite clear enough:.You are not meant to append it to the scope, just to the "resource id". And with resource id they mean the "api://" parts without the name of the permission.

So where you normally request api://<webApiAppId>/access_as_user, for the client-credentials flow you have to request api://<webApiAppId>/.default

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文