资源“此处的 GUID 值”不存在或其查询的引用属性对象之一不存在
Posted
技术标签:
【中文标题】资源“此处的 GUID 值”不存在或其查询的引用属性对象之一不存在【英文标题】:Resource 'GUID value here' does not exist or one of its queried reference-property objects are not present 【发布时间】:2019-10-26 01:37:18 【问题描述】:我正在尝试更改 Azure AD 用户密码。
用户已在 SPA 应用程序中使用 隐式流 和 adal
库进行身份验证。
通话时:
return await graphClient.Me.Request().UpdateAsync(new User
PasswordProfile = new PasswordProfile
Password = userPasswordModel.NewPassword,
ForceChangePasswordNextSignIn = false
,
);
我遇到了这个异常:
"代码:Request_ResourceNotFound\r\n消息:资源 '35239a3d-67e3-4560-920a-2e9ce027aeab' 不存在或其之一 查询的引用属性对象不存在。\r\n\r\n内部 错误\r\n"
调试我使用Microsoft Client SDK
获得的访问令牌我看到这个GUID 指的是oid
和sub
属性。见下文:
这是我用来获取令牌的代码:
IConfidentialClientApplication clientApp =
ConfidentialClientApplicationBuilder.Create(Startup.clientId)
.WithAuthority(string.Format(AuthorityFormat, Startup.tenant))
.WithRedirectUri(Startup.redirectUri)
.WithClientSecret(Startup.clientSecret)
.Build();
var authResult = await clientApp.AcquireTokenForClient(new[] MSGraphScope ).ExecuteAsync();
return authResult.AccessToken;
我在 SPA 应用程序中使用 隐式流。在执行ClaimsPrincipal.Current
时,我看到我的用户已通过身份验证并且所有声明都存在。
我已经阅读了很多文档@GitHub 和 Microsoft Docs,但我仍然不清楚如何实现这一点。 顺便说一句,我正在使用这些 Microsoft Graph 包:
<package id="Microsoft.Graph" version="1.15.0" targetFramework="net461" />
<package id="Microsoft.Graph.Auth" version="0.1.0-preview.2" targetFramework="net461" />
<package id="Microsoft.Graph.Core" version="1.15.0" targetFramework="net461" />
我想我没有接近这个正确性,因为我应该为用户获取一个令牌,而不是为应用程序获取令牌。我应该改用clientApp.AcquireTokenOnBehalfOf
吗?
如果是这样,使用 Microsoft Graph API SDK 为当前登录的用户获取令牌的推荐方法是什么?
你能解释一下吗?
#######编辑#######
我能够使用这个取得一些进展:
var bearerToken = ClaimsPrincipal.Current.Identities.First().BootstrapContext as string;
JwtSecurityToken jwtToken = new JwtSecurityToken(bearerToken);
var userAssertion = new UserAssertion(jwtToken.RawData, "urn:ietf:params:oauth:grant-type:jwt-bearer");
IEnumerable<string> requestedScopes = jwtToken.Audiences.Select(a => $"a/.default");
var authResult = clientApp.AcquireTokenOnBehalfOf(new[] MSGraphScope , userAssertion).ExecuteAsync().GetAwaiter().GetResult();
return authResult.AccessToken;
但现在我得到了错误:
权限不足,无法完成操作。 授权请求被拒绝
【问题讨论】:
刚刚发布了这个问题,我发现了这个github.com/AzureAD/microsoft-authentication-library-for-dotnet/… 我有点困惑。您提到使用隐式 OAuth 授权,但您获得的令牌包含Roles
而不是 scp
。角色是应用程序应对(客户端凭据),这意味着您在这里没有使用隐式。您想要的是使用 Directory.AccessAsUser.All
范围的隐式。
澄清一下,应用程序范围 (roles
) 不能用于重置用户密码。只有委托范围支持重置密码。这确保了任何密码重置都可以被审核回特定用户(正如他们所说的“窒息的喉咙”)。
@MarcLaFleur 感谢您的光临和澄清。我求助于使用原始的clientApp.AcquireTokenForClient
而不是clientApp.AcquireTokenOnBehalfOf
。在下面发布了答案。
【参考方案1】:
经过长时间的调试(大约 8 小时),在看到 @Michael Mainer 的 this answer 后,我终于能够得到我想要的。
这是我放在一起的“正确”代码:
public async Task<User> ChangeUserPassword(UserPasswordModel userPasswordModel)
try
var graphUser = ClaimsPrincipal.Current.ToGraphUserAccount();
var newUserInfo = new User()
PasswordProfile = new PasswordProfile
Password = userPasswordModel.NewPassword,
ForceChangePasswordNextSignIn = false
,
;
// Update the user...
return await graphClient.Users[graphUser.ObjectId].Request().UpdateAsync(newUserInfo);
catch(Exception e)
throw e;
注意 1:
graphClient.Users[graphUser.ObjectId]
被使用而不是graphClient.Me
注意 2:
.ToGraphUserAccount()
来自 Microsoft.Graph.Auth。
我在Postman 中有一个示例PATCH
请求,该请求正确地为用户设置了新密码。
Postman 的 Authorization
请求标头中使用的 访问令牌 与我使用 Microsoft Graph API 获得的格式\属性相同。我只是使用jwt.io 比较了它们。所以我一定是叫错了什么……
我改用clientApp.AcquireTokenForClient
:
var authResult = await clientApp.AcquireTokenForClient(new[] MSGraphScope ).ExecuteAsync();
return authResult.AccessToken;
地点:
MSGraphScope = "https://graph.microsoft.com/.default"
【讨论】:
以上是关于资源“此处的 GUID 值”不存在或其查询的引用属性对象之一不存在的主要内容,如果未能解决你的问题,请参考以下文章
无法找到资源。 说明: HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改
MVC 3.0错误 HTTP 404您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确。
说明: HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改 【怎么解决呢?】