同意流程如何确定要请求哪些资源?

How does the consent flow determine which resources to ask for?

我有一个公开自定义 API 的多租户服务主体。使用 MSAL.js' UserAgentApplication,我可以就首次使用 loginPopup 时所需的资源请求同意。但是,我对在请求中指定哪些资源感到困惑。例如,假设我使用以下弹出窗口(注意缺少范围):

await this.userAgentApplication.loginPopup({
    prompt: 'consent',
    authority: "https://login.microsoftonline.com/organizations"
})

应用程序只会请求用户的个人资料。很公平。

但是,假设我按如下方式配置弹出窗口:

await this.userAgentApplication.loginPopup({
  scopes: ["api://xyz/Some.Scope"]
  prompt: "consent"
  authority: "https://login.microsoftonline.com/organizations"
})

这会导致异常:

The user or administrator has not consented to use the application with ID 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx' named 'XYZ'. Send an interactive authorization request for this user and resource.

为什么即使我使用全局管理员帐户登录也会出现此错误?

最后,除了我们自己的 API 数据之外,我们还需要能够在应用程序上下文中读取图形组,因此我使用 .default 端点请求了这些数据(权限在服务主体注册中指定) .我使用以下弹出窗口执行此操作:

await this.userAgentApplication.loginPopup({
    scopes: ["https://graph.microsoft.com/.default"],
    prompt: 'consent',
    authority: "https://login.microsoftonline.com/organizations"
})

最后一次尝试的结果是...我希望获得的所有权限!

Sign in and read user profile

Read and write all groups

My Custom API scope (Application name)

但为什么我们的 Graph 同意请求会自动包含对其他自定义范围的请求?

如果您对资源使用管理员同意,这是预期的行为。

设置范围***/.default时,相当于在Azure portal中执行"Grant admin consent for {your tenant}"。

所以它会请求管理员同意所有必需的权限,无论它们是否来自所需的资源。

但是如果你设置https://graph.microsoft.com/user.read,它只会要求你同意user.read权限。

所以在这种情况下,一旦你使用最后一个做了管理员同意,api://xyz/Some.Scope也会生效。

我也用我的自定义 API api://***/.defaultapi://***/user.write 进行了测试,两者都按预期工作。

您也可以尝试使用以下请求进行管理员同意:

https://login.microsoftonline.com/jmaster.onmicrosoft.com/oauth2/v2.0/authorize?
client_id={client id}
&response_type=code
&redirect_uri={redirect url}
&response_mode=query
&scope=api://xyz/Some.Scope
&state=12345
&prompt=consent

请使用 api://***/.default 重试。如果它不起作用,请不要担心,因为 api://xyz/Some.Scope 也会使用最后一个代码片段生效。