我正在使用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
。根据{{3}}的beta参考,最低要求的许可是User.Read
,而根据get user的参考,最低要求的许可也是User.Read
。我还使用get photo确认了我应该使用我所拥有的权限来访问照片,尽管我没有在个人资料上设置任何图片,所以它给了我404
响应。
我不知道为什么无法访问个人资料照片,因此非常感谢任何建议。如果您需要更多信息或详细信息,请告诉我。如果相关的话,我有一个自定义的中间件,该中间件处理读取用户信息的身份验证后的过程,该过程还会对照片的MS Graph进行附加调用。
我还尝试了https://graph.microsoft.com/beta/users/{my-user-id}/photo/$value
,它产生了相同的结果-在Graph Explorer中为404,在我的代码中为401
这是我正在使用的代码。第一个代码段位于中间件中,该中间件将经过身份验证的用户的声明以特定格式放入。我刚刚在返回值上设置了一个断点,并检查了响应对象。
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;
}
这是从缓存中获取令牌的函数。 MSALSessionCache
是我从Graph Explorer借来的一些代码,并进行了一些调整以适应.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();
}
}
初始代币获取
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);
}
};
按照Marc LaFleur的要求,我尝试了v1.0端点,结果相同。 https://graph.microsoft.com/v1.0/me
给出200 OK
响应代码,而https://graph.microsoft.com/v1.0/me/photo/$value
返回401 Unauthorized
答案 0 :(得分:1)
当我尝试在/V1.0和/ beta API端点上查询用户的照片或照片的元数据时,Microsoft Graph出现401 Unauthorized异常的问题也相同。像您一样,我确认自己拥有正确的令牌,并且能够成功访问用户个人资料API。
在我的情况下,我发现这是因为尚未设置要测试的用户的照片。分配照片后,我就可以成功调用照片值和照片元数据 beta 端点。
v1.0终结点仍然给我一个401未经授权的异常,但是在我的应用程序中,我仅使用AzureAD,而不使用Exchange。基于@MarcLaFleur注释和API documentation,这听起来像是“预期”行为。
我不知道为什么它返回401 Unauthorized而不是类似404 Not Found之类的消息,或者返回空值。