尽管授予了权限,但图API不断返回Authorization_RequestDenied

时间:2017-04-24 08:39:07

标签: azure microsoft-graph azure-ad-b2c azure-ad-graph-api

我们正在尝试使用Graph API来设置Azure AD管理的用户帐户的属性。我们的想法是,在用户完成注册策略后,我们调用后端Web API(由Azure AD提供)以设置用户无法自行设置的某些属性(例如,我们为新用户提供的内部客户ID)。

不幸的是,当尝试发送更新用户的补丁请求时,Graph API会不断返回异常(“权限不足以竞争此操作”)。 我正在尝试将所有用户的权限授予管理员,因为在更新帐户时没有用户登录。我基本上希望我的应用程序成为能够自动管理用户配置文件的第三方。

我的代码如下所示:

public class GraphAPIClient
{
    private AuthenticationContext authContext;
    private ClientCredential clientCredential;
    private string adTenant;

    public GraphAPIClient(string tenant, string clientID, string clientSecret)
    {
        authContext = new AuthenticationContext("https://login.microsoftonline.com/" + tenant);
        clientCredential = new ClientCredential(clientID, clientSecret);
        adTenant = tenant;
    }

    public async Task<string> UpdateUserInfo(string objectID, string jsonUpdate)
    {
        return await SendPatchRequest("/users/" + objectID, jsonUpdate);
    }

    private async Task<string> SendPatchRequest(string api, string jsonRequest)
    {
        AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://graph.windows.net/", clientCredential);
        HttpClient httpClient = new HttpClient();
        string url = "https://graph.windows.net/" + adTenant + api + "?" + "api-version=1.6";

        HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), url);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        request.Content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");

        HttpResponseMessage response = await httpClient.SendAsync(request);
        if(!response.IsSuccessStatusCode)
        {
            string error = await response.Content.ReadAsStringAsync();
            object formattedError = JsonConvert.DeserializeObject(error);
                throw new Exception("Graph API request failed:\n" + JsonConvert.SerializeObject(formattedError, Formatting.Indented));
        }

        return await response.Content.ReadAsStringAsync();
    }
}

我正在使用已注册应用程序的应用程序ID,目录的租户以及我在Azure中生成的密钥作为客户端密钥。我成功收到了一个令牌。

我尝试了什么:

  • 我设置了(或者我认为我有)编辑用户所需的权限。我使用管理员帐户点击了“授予权限”,并在Azure面板中查看时显示了权限: Image
  • 我设置了“读写所有用户的完整配置文件”和“读写目录数据”。这些任务的权限是否正确?
  • 我还尝试使用新的应用程序注册控制台,但是在尝试获取令牌时,我得到了“无法建立调用应用程序的标识”异常。在此控制台中创建的应用程序在常规Azure AD面板中不可见。

任何人都可以帮我吗?我已经彻底搜索过了,但是关于这个问题的大多数问题都比较旧,建议使用旧的Azure面板。我已经尝试了它仍然无法工作,我认为新的Azure面板最近才收到AD编辑功能,并且在提出这些问题时没有它们。

非常感谢 - 如果您需要更多信息,我很乐意提供。

1 个答案:

答案 0 :(得分:0)

您的方案和代码都反映了客户端凭据流和应用程序权限的使用。但是,您从Azure门户截取的屏幕截图仅显示已设置的委派权限。

根据您需要的权限/操作类型,您可以使用两种方法:

  1. 最容易设置但有限的权限集:通过Azure门户。确保从“应用程序权限”中选择权限,然后单击授予权限。如果没有显示,那是因为您已将应用程序创建为Native应用程序。对于安全地安装在服务器端的无头客户端(不交给最终用户),您应该选择Web应用程序/ API,这样您就可以访问应用程序权限:

    Application permissions in Azure Portal

  2. 最难设置但最广泛的权限集:通过PowerShell。如果您希望能够删除用户,这是唯一可行的选项。您需要获取应用程序的ServicePrincipalID,然后向服务主体授予所需的角色,如下所示:

    $appDisplayName = <Your-app-display-name>
    
    $msolcred = Get-Credential
    Connect-MsolService -credential $msolcred
    
    $servicePrincipal = Get-MsolServicePrincipal | where DisplayName -eq $appDisplayName
    $objectId = $servicePrincipal.ObjectId.ToString()
    
    Add-MsolRoleMember -RoleObjectId 88d8e3e3-8f55-4a1e-953a-9b9898b8876b -RoleMemberObjectId $objectId -RoleMemberType servicePrincipal
    Add-MsolRoleMember -RoleObjectId 9360feb5-f418-4baa-8175-e2a00bac4301 -RoleMemberObjectId $objectId -RoleMemberType servicePrincipal
    Add-MsolRoleMember -RoleObjectId fe930be7-5e62-47db-91af-98c3a49a38b1 -RoleMemberObjectId $objectId -RoleMemberType servicePrincipal
    

    或者,您可以按照this article.中的步骤操作。