如何为 GraphServiceClient 设置资源 URL 以获取组?

How to set resource URL for GraphServiceClient to fetch Groups?

我正在尝试使用从 JWT access token 中的 _claims_sources 收到的 groups:src1 端点值从图表 API 中获取广告组。

我的客户端正在使用客户端凭据,可以获取 AD 中所有用户和组的信息。

我是这样设置的:

private async Task<IList<Group>> GetUserGroupsAsync(string endpoint)
{
    // Endpoint is from the claims in a previous OIDC request

    // Setup a client if it does not exist
    PrepareGraphApiClient();

    // I can fetch my groups using the methods in the client
    // var groupPage = await graphServiceClient.Me.MemberOf.Request().GetAsync();

    // This is where I would like to use the resource URL received from the
    // claims I receive in a previous OIDC request
    var groupPageFromUrl = ???

    ...
}

private void PrepareGraphApiClient()
{
    if (graphServiceClient != null) return;

    try
    {
        AuthenticationContext authority = new AuthenticationContext(oidcOptions.Authority);
        ClientCredential clientCredential = new ClientCredential(oidcOptions.ClientId, oidcOptions.ClientSecret);

        var graphApiResource = "https://graph.microsoft.com";
        AuthenticationResult authenticationResult = authority.AcquireTokenAsync(graphApiResource, clientCredential).Result;

        graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider(
            async requestMessage =>
            {
                // Add token to outgoing requests
                requestMessage.Headers.Authorization =
                    new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
            }));
    }
    catch (Exception ex)
    {
        logger.LogDebug($"Could not create the graph client {ex}");
        throw;
    }
}

我可以使用 GraphServiceClient 声明中的资源 URL 还是必须设置 HttpClient 才能发出请求?

_claim_sources.src1 中标识的端点用于 Azure AD Graph,因此您使用的令牌需要用于 Azure AD Graph API (https://graph.windows.net),而不是用于 Microsoft Graph (https://graph.microsoft.com)。这也意味着您不能使用 Microsoft Graph SDK,因为 API 请求和响应根本不同。

您有两个选择:

  1. (推荐)使用端点仅作为您必须进行查找的指示这一事实,并向 Microsoft 发出 等效 调用使用 Microsoft Graph SDK 的图形:

    var memberOfIds = await graphServiceClient
            .Users[userObjectId]                          # from the 'oid' in access token
            .GetMemberObjects(securityEnabledOnly: true) # true if groupMembershipClaims is "SecurityGroup", false if it's "All"
            .Request()
            .PostAsync();
    
  2. 使用给定的终结点并使用(例如)HttpClient 构建您自己的 Microsoft Graph 请求。一个简单的例子:

    using (var client = new HttpClient())
    {
        # Always get the token right before you use it. ADAL will take care of getting a new one
        # if needed, or using an existing cached token if not.
        authenticationResult = 
            authority.AcquireTokenAsync("https://graph.windows.net", clientCredential)
        client.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
    
        # Make the API request to Azure AD Graph. Note we have to include the api-version and
        # the request body.
        HttpResponseMessage response = await client.PostAsync(
            $"{src}?api-version=1.6", new StringContent(
                "{'securityEnabledOnly': true}", # true if groupMembershipClaims is "SecurityGroup", false if it's "All"
                UnicodeEncoding.UTF8,
                "application/json"));
        if (response.IsSuccessStatusCode)
        {
            # Note we're deserializing as if it were a Microsoft Graph response to getMemberObjects,
            # rather than an Azure AD Graph response. Though it works, this is somewhat risky, and
            # it would be more correct to explicitly define the form of an Azure AD Graph response.
            var memberOfIds = JsonConvert.DeserializeObject<DirectoryObjectGetMemberObjectsCollectionResponse>(
                await response.Content.ReadAsStringAsync()).Value;
        }
    }
    

作为旁注,我注意到您有一个调用来获取您已提供给 Microsoft Graph 库的 DelegateAuthenticationProvider 之外的 令牌。您应该将 AcquireTokenAsync 调用 放在 中,以便它为每个 Microsoft Graph 请求检索一个新令牌。库 (ADAL) 将负责使用缓存令牌(如果可用)或发出新令牌请求(如果 none 可用或可用令牌已过期)。像这样:

    graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider(
        async requestMessage =>
        {
            // Get fresh token
            AuthenticationResult authenticationResult = 
                await authority.AcquireTokenAsync(graphApiResource, clientCredential);

            // Add token to outgoing requests
            requestMessage.Headers.Authorization =
                new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
        }));