【问题标题】:"Microsoft.Office365.Discovery.DiscoveryFailedException: Unauthorized" when creating a DiscoveryClient object创建 DiscoveryClient 对象时出现“Microsoft.Office365.Discovery.DiscoveryFailedException: Unauthorized”
【发布时间】:2025-12-03 02:55:01
【问题描述】:

我有一个尝试与 Office 365/Azure AD 集成的 ASP.Net MVC 5 Web 应用程序。

该应用程序成功地允许登录/退出,并成功地将 Graph API 调用和调用权限委派给我的一个单独的 Web API,该 Web API 对 Azure AD 进行身份验证。所以,有些东西在起作用。

但是,在尝试创建 DiscoveryClient 对象时,我在 DiscoveryFailedException 中收到 Unauthorised ErrorCode。

犯法:

public static async Task<SharePointClient> CreateSharePointClientAsync(string capability)
{
    var signInUserId = ClaimsPrincipal.Current.FindFirst(System.IdentityModel.Claims.ClaimTypes.NameIdentifier).Value;
    var userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

    AuthenticationContext ctx = new AuthenticationContext(OfficeSettings.Authority, new NaiveSessionCache(signInUserId));
    var credential = new ClientCredential(OfficeSettings.ClientId, OfficeSettings.ClientSecret);
    var userIdent = new UserIdentifier(userObjectId, UserIdentifierType.UniqueId);

    try
    {
        DiscoveryClient discoClient = new DiscoveryClient("https://api.office.com/discovery/v1.0/me/",
             async () =>
             {
                 var authResult = await ctx.AcquireTokenAsync("https://api.office.com/discovery/",
                                                              credential);
                 return authResult.AccessToken;
             });

        var capabilityResult = await discoClient.DiscoverCapabilityAsync(capability);
        return new SharePointClient(capabilityResult.ServiceEndpointUri,
            async () =>
            {
                var authResult = await ctx.AcquireTokenAsync(capabilityResult.ServiceResourceId,
                                                              credential);
                return authResult.AccessToken;
            });
    }
    catch (AdalException ex)
    {
        if (ex.ErrorCode == AdalError.FailedToAcquireTokenSilently)
        {
            ctx.TokenCache.Clear();
            throw ex;
        }
        return null;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

在 DiscoveryClient 实例化的 lambda 中调用 ctx.AcquireTokenAsync 时发生错误。

如上所述,应用程序可以登录用户,因此 ClientId/Secret 必须是正确的,我也相信这需要的权限类似于使用发现服务所需的权限。

我还尝试跳过发现步骤,只是为 Sharepoint 客户端硬编码 ResourceId,看看我是否可以暂时保持这种状态;但是,尽管在 AAD 管理页面中为应用程序授予了适当的权限,但我也在这里遇到了一些权限错误。

我完全不知所措;从 O365-ASPNETMVC-Start 运行示例应用程序的工作方式与您预期的一样,使用相同的凭据登录 Office 365。 为了尝试查明问题,(我认为相关的)代码现在实际上与(工作)示例相同,但仍然没有运气。

如果任何其他代码对解决问题有用,我会很乐意分享。

任何想法都将不胜感激。

【问题讨论】:

  • 你好,这个问题你解决了吗,我现在也有同样的问题。

标签: c# asp.net-mvc office365 adal


【解决方案1】:

首先,我没有尝试更改 O365-ASPNETMVC-Start 示例以使用统一 API 端点(Graph API)。虽然我还没有尝试过你在做什么,但我希望发现调用在针对统一 API 时不起作用。当您需要发现端点时,discoveryClient 很有用。由于只有一个端点,因此无需发现它。我建议您查看Office 365 unified API overview (preview) 了解更多背景信息。

我建议您查看 Office 365 Profile sample for Windows,因为它使用统一端点。它使用统一的 API 客户端库,如果以统一端点为目标,您将要使用该库。

请注意,统一 API 处于预览阶段。 O365-ASPNETMVC-Start 示例使用的 API 是当前认可用于生产的。

请用 [Office365] 标签标记您的问题,以便其他感兴趣的人可以看到您的问题。

关于,

【讨论】:

  • 感谢您的帮助;诚然,我误解了 Graph API 的用途,但我现在明白了!但是,在拖动其中一些东西时,我仍然遇到同样的问题,试图找出原因。我认为统一的 API 可能是红鲱鱼?原因是,我只用它来检索主授权流程之外的用户个人资料信息(我最初的误解是它是一个“用户图”API,doh)。我对统一 API 的唯一剩余引用也出现在 O365-ASPNETMVC-Start 示例中(Startup.Auth.cs,第 59 行)。
  • 好的,我现在正在使用 AcquireTokenByAuthorizationCodeAsync 来解决这个问题,它正在工作。鉴于示例项目中的支持​​代码有效,不知道我现在的实际问题在哪里。可能与 VS 2013 中的项目模板有关,做了一些我没想到的事情,O365 示例中似乎没有其他 WIF 内容。
  • @Dean Becker 我们如何在不重定向用户的情况下获得授权码?