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

时间:2019-06-25 09:40:56

标签: .net-core azure-active-directory microsoft-graph azure-ad-graph-api

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

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

这是我的设置方式:

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进行请求?

1 个答案:

答案 0 :(得分:1)

_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 Graph SDK对Microsoft Graph进行等效调用:

    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)将负责使用缓存的令牌(如果可用)或发出新的令牌请求(如果没有可用或可用的令牌已过期)。像这样:

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