使用图 API 从多租户 AD 应用程序中获取所有用户

Get all the users from multi-tenant AD Application using graph API

我正在尝试使用图表 API 获取多租户应用程序的所有用户。为此,我使用请求生成了访问令牌:

POST https://login.microsoftonline.com/common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=qWgdYAmab0YSkuL1qKv5bPX
&grant_type=client_credentials

注意: 请注意,在上面的请求中,我使用 common 代替了 {tenantID}。这只是一次尝试,因为在 doc.

中对 adminConsent 提出了同样的建议

通过使用上面生成的访问令牌,我请求用户 API 并得到以下错误

{
    "error": {
        "code": "Authorization_IdentityNotFound",
        "message": "The identity of the calling application could not be established.",
        "innerError": {
            "request-id": "56141b7d-dd5e-44b1-9395-cd15d02b52de",
            "date": "2019-06-17T12:42:19"
        }
    }
}

并且当我使用租户 ID 生成令牌时,它只有 returns 个活动目录的用户。

任何人都可以建议我哪里错了吗?

由于您使用的是公共端点,因此您不能在此处使用客户端凭据流(无需用户即可访问)。您需要参考这个document(代表用户获取访问权限)。

注意:当您使用授权码授权流程(代表用户获取访问权限)时,您需要授予委派权限而不是申请许可。

获取访问令牌

在 Multi-tenant 应用程序中,服务主体对象是在访问该应用程序的每个租户中创建的。这些服务主体对象将持有特定于该租户的同意 (user/admin) 对象,并且机密也链接到这些对象。

因此当您获得令牌时,它始终是 tenant-specific 并且您需要为每个租户获取单独的令牌才能在该租户中执行任何操作。

示例:假设您在租户 A 中注册了一个 multi-tenant 应用程序,并且也被租户 B、C 和 D 使用。这也会在租户 B、C 和 D 中创建 SP 对象。

因此,如果您需要在租户 B 中执行任何操作,则需要 SP B 的令牌并使用与其关联的秘密。

简而言之,如果你想在应用程序的上下文中执行这些操作,你需要所有租户的信用。

我最近不得不实施这个,并且在那个方面取得了成功。这些是我完成的步骤。

  1. 创建了一个 multi-tenant 应用程序
  2. 授予应用程序权限
  3. 使用 tenant-specific 身份验证 header 配置 GraphClient。

这是获取 tenant-specific 图形客户端的代码。

private ClientCredentialProvider GetGraphAuthProvider(Guid tenantId) {
            IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
                .Create(_configuration["AzureAd:ClientId"])
                .WithTenantId(Convert.ToString(tenantId))
                .WithClientSecret(_configuration["AzureAd:ClientSecret"])
                .Build();
            return new ClientCredentialProvider(confidentialClientApplication);
        }

        public GraphServiceClient GetGraphServiceClient(Guid tenantId) = >new GraphServiceClient(GetGraphAuthProvider(tenantId));
    }
}

我已经在my blog here中解释了所有内容。

我看到您正在尝试使用 "common" 获取应用程序级访问令牌,并且您没有在请求中的任何地方指定租户 ID。您可以在 url: https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token 中指定租户 ID,也可以在请求正文中指定它。在这种情况下,您的请求应如下所示:

POST https://login.microsoftonline.com/common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id={client Id}
&scope={scopes, in your case ".default"}
&client_secret={client secret}
&tenant_id={organization's tenant id}
&grant_type=client_credentials