MS Graph - 401看似未经授权,具有适当的令牌和访问权限

Nik*_*oem 5 c# azure microsoft-graph azure-ad-msal asp.net-core-2.0

我正在使用Azure上托管的ASP.NET Core 2.0应用程序,并使用MSAL通过Microsoft对用户进行身份验证.我通过身份验证过程获取基本信息,如名称,用户名和组声明.但是,我想通过MS Graph访问一些其他信息,例如用户个人资料照片.初始身份验证和令牌获取平稳运行,并向https://graph.microsoft.com/beta/me返回发送请求200 OK.https://graph.microsoft.com/beta/me/photo/$value然而,当试图打电话时,我得到一个401 - Unauthorized回报.

我在这个问题上看到了其他几篇文章,但大多数人都认为开发人员忘记要求正确的同意,从错误的端点获取令牌或类似的问题.所有这些我都证实不是这样的.

我已经确认使用https://jwt.ms/在令牌中包含了适当的范围.我也尝试过要求更大的范围.目前我正在使用以下范围:openid profile User.ReadBasic.All User.Read.All User.ReadWrite Files.ReadWrite.All.根据获取用户的beta参考,最少需要的权限是,User.Read并根据获取照片的参考,最少需要的权限也是User.Read.使用Graph Explorer我还确认我应该使用我的权限访问该照片,但是,我没有在我的个人资料上设置任何图片,因此它给了我一个404回复.

我不知道为什么我无法访问个人资料照片,所以任何建议都非常感谢.如果您需要更多信息或详细信息,请告诉我们.如果相关,我有一个自定义中间件来处理读取用户信息的后验证过程,这也会对照片的MS Graph进行额外调用.

编辑:

我也试过https://graph.microsoft.com/beta/users/{my-user-id}/photo/$value产生相同的结果 - 图形浏览器中的404和我的代码中的401

编辑2:代码

这是我正在使用的代码.第一个代码段位于中间件中,该中间件将来自经过身份验证的用户的声明置于特定格式.我刚刚在返回时设置了一个断点并检查了响应对象.

public async Task GetUserPhotoAsync(string userid, HttpContext context)
{
    HttpClient client = new HttpClient();
    //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var result = await new TokenHelper(_settings).GetAuthenticationAsync(userid, context, new string[] { "User.ReadBasic.All", "User.Read.All", "User.ReadWrite", "Files.ReadWrite.All" });
    var url = "https://graph.microsoft.com/beta/me/photo/$value";
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
    HttpResponseMessage response = await client.SendAsync(request);

    return;
}
Run Code Online (Sandbox Code Playgroud)

这是从缓存中获取令牌的函数.MSALSessionCache是我从这里借来的一些代码,通过一些调整来适应.net核心.

public async Task<AuthenticationResult> GetAuthenticationAsync(string signedInUserId, HttpContext context, string[] scopes)
{
    TokenCache userTokenCache = new MSALSessionCache(signedInUserId, context).GetMsalCacheInstance();


    ConfidentialClientApplication cca = 
        new ConfidentialClientApplication(_settings.ClientId, $"{_settings.Domain}/{_settings.AADInstance}/v2.0", "http://localhost:5000", new ClientCredential(_settings.ClientSecret), userTokenCache, null);


    if (cca.Users.Count() > 0)
    {
        AuthenticationResult result = await cca.AcquireTokenSilentAsync(scopes, cca.Users.First());
        return result;
    }
    else
    {
        throw new Exception();
    }

}
Run Code Online (Sandbox Code Playgroud)

初始令牌获取

options.Events = new OpenIdConnectEvents
{
    OnAuthorizationCodeReceived = async context =>
    {
        string signedInUserId = context.Principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        TokenCache userTokenCache = new MSALSessionCache(signedInUserId, context.HttpContext).GetMsalCacheInstance();

        ConfidentialClientApplication cca =
        new ConfidentialClientApplication(aadOptions.ClientId, aadOptions.RedirectUri, new ClientCredential(aadOptions.ClientSecret), userTokenCache, null);

        AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(context.ProtocolMessage.Code, new string[] { "User.ReadBasic.All", "User.Read.All", "User.ReadWrite", "Files.ReadWrite.All" });
        context.HandleCodeRedemption(result.AccessToken, result.IdToken);

    }
};
Run Code Online (Sandbox Code Playgroud)

编辑3:使用/v1.0端点

根据Marc LaFleur的要求,我尝试了v1.0端点,结果相同.返回时https://graph.microsoft.com/v1.0/me给出200 OK响应代码https://graph.microsoft.com/v1.0/me/photo/$value401 Unauthorized

nbr*_*wne 1

当我尝试在 /V1.0 和 /beta API 端点上查询用户的照片或照片的元数据时,Microsoft Graph 也遇到了同样的问题,给出了 401 未经授权的异常。和您一样,我验证了我拥有正确的令牌并且能够成功访问用户配置文件 API。

就我而言,我发现这是因为我正在测试的用户的照片尚未设置。分配照片后,我就能够成功调用照片值和照片元数据beta端点。

v1.0 端点仍然给我一个 401 未经授权的异常,但在我的应用程序中我只使用 AzureAD,而不是 Exchange。根据 @MarcLaFleur 评论和API 文档,这听起来像是“预期”行为。

我不知道为什么它返回 401 Unauthorized 而不是 404 Not Found 或返回 null 值。