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

5

我正在尝试使用图形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}。那只是一种尝试,因为在文档中建议对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生成令牌时,它只返回一个活动目录的用户。

有人能建议一下,我错在哪里了吗?

4个回答

2
由于您正在使用通用终结点,因此您不能在此处使用客户端凭据流(无需用户即可访问)。 您需要参考此文档(代表用户获取访问权限)。
注意:当您使用授权代码授予流程(代表用户获取访问权限)时,您需要授予委派权限而不是应用程序权限。

enter image description here

获取访问令牌

enter image description here


1
如果您的令牌中没有User.Read.All权限,则需要将范围标识为“https://graph.microsoft.com/User.Read.All”@mohitsharma。 - Tony Ju
抱歉回复晚了,我在等待其他租户管理员提供管理同意。之后,我尝试了一下但仍然得到相同的响应。我解码了 Token,其中 scp 是这样的:"scp": "Files.ReadWrite Files.ReadWrite.All Group.ReadWrite.All IdentityProvider.Read.All Mail.Read profile User.Read User.Read.All User.ReadBasic.All openid email"。 - mohit sharma
@mohitsharma 是的,这是预期的结果。您将从授予管理员同意的所有AD租户中获取用户吗? - Tony Ju
@mohitsharma 这是不可能的。只有当您登录时,您的应用程序才会知道租户信息。如果来自A租户的用户A登录,您只能获取来自A租户的用户。 - Tony Ju
@mohitsharma 这个令牌始终是特定于租户的。 - Tony Ju
显示剩余3条评论

1
在多租户应用程序中,将在每个租户中创建服务主体对象以访问应用程序。这些服务主体对象将保存特定于该租户的同意(用户/管理员)对象,并且密钥也与这些对象相关联。
因此,当您获得令牌时,它始终是特定于租户的,您需要为每个租户获取单独的令牌才能在该租户中执行任何操作。
例如:假设您在租户A中注册了一个多租户应用程序,并且租户B、C和D也在使用它。这也将在租户B、C和D中创建SP对象。
因此,如果您需要在租户B中执行任何操作,则需要使用与SP B关联的密钥获取SP B的令牌。
简而言之,如果您想在应用程序的上下文中执行这些操作,则需要从所有租户获取凭据。

0

最近我不得不实现这个功能,并且取得了成功。以下是我所采取的步骤:

  1. 创建了一个多租户应用程序
  2. 授予应用程序权限
  3. 使用特定于租户的身份验证头配置了GraphClient。

以下是获取特定于租户的图形客户端的代码。

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

我已经在这里的我的博客中解释了一切。


0

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接