Azure active directory 使用应用程序标识访问Azure Graph API

Azure active directory 使用应用程序标识访问Azure Graph API,azure-active-directory,azure-ad-graph-api,Azure Active Directory,Azure Ad Graph Api,我正在使用Azure Graph API,我注意到我无法读取通过许可框架注册的目录 一切都适用于用户级权限。也就是说,用 private async Task<string> AcquireGraphApiTokenAsync(string objectId, AuthenticationContext authContext) { var result = await authContext.AcquireTokenSilentAsync( GraphUrl

我正在使用Azure Graph API,我注意到我无法读取通过许可框架注册的目录

一切都适用于用户级权限。也就是说,用

private async Task<string> AcquireGraphApiTokenAsync(string objectId, AuthenticationContext authContext)
{
    var result = await authContext.AcquireTokenSilentAsync(
        GraphUrl, _clientCredential, new UserIdentifier(objectId, UserIdentifierType.UniqueId));
    return result.AccessToken;
}
然而,有时我想在守护进程中运行类似的进程,这就是我遇到麻烦的地方。在这种情况下,我需要使用我的应用程序标识:

private void AuditDirectories(ClientCredential clientCredential, IEnumerable<AzureActiveDirectory> directories)
{
    foreach (var directory in directories)
    {
        var authContext = new AuthenticationContext(string.Format(CultureInfo.InvariantCulture, AadInstance, directory.Domain));
        var result = authContext.AcquireToken(GraphUrl, clientCredential);
        var graphServiceRoot = string.Format("{0}/{1}", GraphUrl, directory.TenantId);
        var graphClient = new ActiveDirectoryClient(new Uri(graphServiceRoot), () => Task.FromResult(result.AccessToken));
        foreach (var user in _userQuery.Office365Users(directory))
        {
            CheckThatAccountExistsAndIsEnabled(graphClient, user);
        }
    }
}
抛出错误“权限不足,无法完成操作”


看起来使用用户身份的委托访问没有任何问题,但是使用应用程序身份的访问失败了,尽管我已经在应用程序级别设置了应用程序权限。

我认为这个问题的当前形式有误导性。您可以以用户身份和应用程序身份获取令牌,并且可以使用
AcquireToken
AcquireTokenSilent
来完成这两件事。应用程序可以在目录中配置为请求不同的权限,这取决于它们是使用应用程序标识访问资源,还是使用用户标识作为委托访问

在您的示例中,您在
AcquireTokenSilent
调用中以用户身份获取令牌,在
AcquireToken
one中以应用程序身份获取令牌,您在应用程序中为这两种情况配置的不同权限导致您观察到的行为不同。但是,这种差异是由您使用的重载决定的,而不是由
AcquireTokenSilent
AcquireToken
之间的任何固有差异决定的


您可以通过门户中的“应用程序权限”下拉列表(而不是“委托权限”)将应用程序配置为具有对Azure AD Graph API的访问权限,但是请注意,您需要是租户管理员才能这样做。

我认为这个问题在其当前形式中具有误导性。您可以以用户身份和应用程序身份获取令牌,并且可以使用
AcquireToken
AcquireTokenSilent
来完成这两件事。应用程序可以在目录中配置为请求不同的权限,这取决于它们是使用应用程序标识访问资源,还是使用用户标识作为委托访问

在您的示例中,您在
AcquireTokenSilent
调用中以用户身份获取令牌,在
AcquireToken
one中以应用程序身份获取令牌,您在应用程序中为这两种情况配置的不同权限导致您观察到的行为不同。但是,这种差异是由您使用的重载决定的,而不是由
AcquireTokenSilent
AcquireToken
之间的任何固有差异决定的


您可以通过门户中的“应用程序权限”下拉列表(而不是“委托权限”)将应用程序配置为具有对Azure AD Graph API的访问权限,但是请注意,您需要是租户管理员才能这样做。

这似乎是无缘无故开始工作的。虽然我很想说这是魔法造成的,但可能还有另一种解释

正如vibronet所解释的,您需要向应用程序添加应用程序权限。完成此操作后,租户管理员有必要再次注册同意框架。我在一个单独的浏览器中这样做,作为应用程序应该读取其目录的租户的管理员。但是,我在设置应用程序权限的几分钟内就这样做了。一天后,当我再次通过同意框架时,该应用程序再次开始工作


如果遇到与我所描述的类似的情况,并且需要更改“应用程序权限”下拉列表,请在租户通过同意框架之前,给它几分钟的时间进行传播。(我假设您至少有一个您是管理员的客户机租户,这样您就可以测试您的应用。)

这似乎是无缘无故开始工作的。虽然我很想说这是魔法造成的,但可能还有另一种解释

正如vibronet所解释的,您需要向应用程序添加应用程序权限。完成此操作后,租户管理员有必要再次注册同意框架。我在一个单独的浏览器中这样做,作为应用程序应该读取其目录的租户的管理员。但是,我在设置应用程序权限的几分钟内就这样做了。一天后,当我再次通过同意框架时,该应用程序再次开始工作


如果遇到与我所描述的类似的情况,并且需要更改“应用程序权限”下拉列表,请在租户通过同意框架之前,给它几分钟的时间进行传播。(我假设您至少有一个您是管理员的客户端租户,以便您可以测试您的应用。)

谢谢。在“应用程序权限”下拉列表中,选中了两个选项(读和读写),因此我不明白为什么会出现这种行为。抱歉,我没有注意到您正在使用Me端点。应用程序没有一个我。。。您的查询要求的是应用程序没有的用户属性。对不起,我并没有这样做。我将编辑问题。编辑问题以提供更多信息。谢谢你的反馈——我也编辑了这个问题以反映这一点。@vibronet你能给我举一个关于如何配置守护程序应用程序以使用应用程序标识的示例吗?我有一个web应用程序可以作为用户获取令牌,但这对我运行更长时间的守护进程没有帮助。谢谢。在“应用程序权限”下拉列表中,选中了两个选项(读和读写),因此我不明白为什么会出现这种行为。抱歉,我没有注意到您正在使用Me端点。应用程序没有一个我。。。您的查询要求的是应用程序没有的用户属性。对不起,我并没有这样做。我会编辑t
private void AuditDirectories(ClientCredential clientCredential, IEnumerable<AzureActiveDirectory> directories)
{
    foreach (var directory in directories)
    {
        var authContext = new AuthenticationContext(string.Format(CultureInfo.InvariantCulture, AadInstance, directory.Domain));
        var result = authContext.AcquireToken(GraphUrl, clientCredential);
        var graphServiceRoot = string.Format("{0}/{1}", GraphUrl, directory.TenantId);
        var graphClient = new ActiveDirectoryClient(new Uri(graphServiceRoot), () => Task.FromResult(result.AccessToken));
        foreach (var user in _userQuery.Office365Users(directory))
        {
            CheckThatAccountExistsAndIsEnabled(graphClient, user);
        }
    }
}
graphClient.Users.Where(u => u.DisplayName == userName).ExecuteAsync().Result.CurrentPage.FirstOrDefault()