使用 Azure AD Graph 客户端更改用户密码的权限问题 API

Permission issue changing user password using Azure AD Graph client API

我正在尝试在 ASP.Net MVC 中创建一个页面来重置当前用户的密码。我正在使用 Azure 活动目录进行用户身份验证。要访问用户的 AD 信息,我使用的是 C# Graph API 客户端。我的代码基于 GitHub

上的示例

我可以更改用户的信息(例如城市、州、电子邮件)。但是,当我尝试使用用户对象上的 PasswordProfile 属性更改密码时,我收到一条错误消息,提示我没有足够的权限。我正在尝试更改应用程序的密码,我认为权限问题的根源在于应用程序。

我发现了以下 PowerShell 脚本,它可以将公司管理员角色添加到应用程序。但是,对 Get-MsolServicePrincipal 的调用不会 return 任何东西。查看命令的输出,我没有看到任何与我的应用程序名称相似的条目。

#-----------------------------------------------------------
# This will prompt you for your tenant's credential
# You should be able to use your your Azure AD administrative user name
# (in the admin@tenant.onmicrosoft.com format)
#-----------------------------------------------------------
import-module MSOnline
Connect-MsolService

#-----------------------------------------------------------
# Replace the Application Name with the name of your 
# Application Service Principal
#-----------------------------------------------------------
$displayName = "My Azure AD Application"
$objectId = (Get-MsolServicePrincipal -SearchString $displayName).ObjectId

#-----------------------------------------------------------
# This will add your Application Service Prinicpal to 
# the Company Administrator role
#-----------------------------------------------------------
$roleName = "Company Administrator"              
Add-MsolRoleMember -RoleName $roleName -RoleMemberType ServicePrincipal -RoleMemberObjectId $objectId

我想我的第一个问题是我是否正确认为权限问题与应用程序有关?

其次,我应该将 $displayName 变量设置为什么值?

您需要确保您在 Azure Active Directory 中的应用程序配置具有适当的权限设置。使用上面的内容添加权限是矫枉过正的。您应该只向目录中的应用程序添加所需的权限。

作为起点,我建议您在此处查看 Graph API Consent Permission 博客 post。您只能使用传统权限以帐户或全局管理员身份重置密码,但您应该分配应用程序权限。

"Read and write directory data" 用于提供此权限,但我相信这已被删除。现在我相信用户必须同意使用 OAuth 身份验证流程才能重置密码。

有关这方面的更多信息,请参阅当前登录用户的 changePassword 方法。我有一个自定义桌面应用程序供用户重置自己的密码。

在我的应用程序中,我让用户使用他们现有的密码进行身份验证以获取访问令牌(这也有助于我在更改密码之前验证他们当前的凭据)。

var authority = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/" + Domain);
var ctx = new AuthenticationContext(authority, false);
var result = ctx.AcquireToken("https://graph.windows.net", "ClientID", credential);
return result.AccessToken;

凭据 属性 是一种使用用户 UPN 和密码的 UserCredential 类型。然后我传递一个网络请求来更改密码。

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", UserAccessToken);
var requestUri = $"https://graph.windows.net/me/changePassword?api-version={Constants.ApiVersion}";
var pwdObject = new { currentPassword = curPassword, newPassword = newPass };
var body = new JavaScriptSerializer().Serialize(pwdObject);
var response = client.PostAsync(new Uri(requestUri), new StringContent(body, Encoding.UTF8, "application/json")).Result;

如果请求成功,此 returns HTTP 204,我还在获取用户令牌时捕获 AADSTS50126 异常,因为这表明在获取令牌时凭据无效。

只有在您授予应用程序正确权限的情况下,您才能从您的应用程序更改密码。 Martyn C 解释的方法是最好的方法,如果你可以模拟用户,当然,用户有权更改他的密码。 使用我的方法,无需使用任何 UserCredentials,因为权限将分配给能够更改其他用户密码的应用程序。 一个典型的用例是当您需要使用非交互式流程管理 api 的密码更改时。 这意味着您必须信任应用程序的代码并谨慎使用它。

我曾经将帮助台管理员角色授予我的应用程序,这足以更改其他用户的密码。 通过这个 powershell 脚本:

Install-Module MSOnline
Install-Module AzureAD
Connect-MsolService
Connect-AzureAD

$applicationId = "{your app ID}"
$sp = Get-MsolServicePrincipal -AppPrincipalId $applicationId
Add-MsolRoleMember -RoleObjectId <your Role ID> -RoleMemberObjectId $sp.ObjectId -RoleMemberType servicePrincipal

您应该使用在 Active Directory 上具有管理员权限的用户进行连接。 您可以使用此命令获取属性 roleID:

Get-AzureADDirectoryRole

现在您的应用程序有足够的权限调用 PATCH 方法(来自 Microsoft Docs)来更改其他用户的密码。