如何在asp.net mvc中使用ms graph api更改AD B2C用户密码

时间:2021-02-26 13:11:09

标签: asp.net-mvc microsoft-graph-api azure-ad-b2c

我想允许用户通过提供当前密码和新密码来更改我的应用程序中的密码(不是重置,而是实际更改)。

查看 documentation 我试过了,调用没有失败,但是旧密码和新密码最终都不起作用,我不得不删除用户。作为参考,我将发布我的代码:

    var graphClient = GetGraphServiceClient();

    var identity = new ObjectIdentity
    {
        Issuer = Globals.Tenant,
        IssuerAssignedId = userEmail,
        SignInType = "emailAddress"
    };

    var user = new User
    {
        PasswordProfile = new PasswordProfile
        {
            Password = newPassword
        },
        Identities = new ObjectIdentity[] { identity }
    };

    await graphClient.Users[userId]
        .Request()
        .UpdateAsync(user);

我从文档中推测并环顾四周,这不是正确的方法,因为我需要代表登录用户而不是应用程序来执行此操作。但是,对于 AD B2C,在门户下,除了 open_id 或 offline_access 之外,我无法向我注册的应用授予委托权限。

遇到 this 后,我认为我需要实际尝试使用登录用户的访问令牌而不是应用程序的访问令牌进行此调用。所以我将用户的令牌代码分配给一个声明,以便我以后可以访问它:

//in startup.auth.cs
 private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
        {
            try
            {
                notification.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", notification.Code));

...

//in changePassword() method:
            //retrieve user access code from the claim stored previously when logging them in.
            var userToken = ClaimsPrincipal.Current.FindFirst("access_token").Value;

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(Globals.GraphApiEndpoint);
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", userToken);
                try
                {
                    JObject o = JObject.FromObject(new
                    {
                        currentPassword,
                        newPassword
                    });
                    await client.PostAsJsonAsync($"v1.0/me/changePassword/", o.ToString());

                }
                catch(Exception ex)
                {
                    //never any exception. always succeeds!
                }
            }

无论我输入什么密码,上面总是成功。但密码显然根本没有改变。我究竟做错了什么?还有其他方法可以做到这一点吗?

编辑:如果我执行以下操作,我的第一种方法似乎有效:

            var user = new User
            {
                PasswordProfile = new PasswordProfile
                {
                    Password = newPassword,
                    ForceChangePasswordNextSignIn = false
                },
                Identities = new ObjectIdentity[] { identity }
            };

            var userInfo = await graphClient.Users[userId]
                .Request()
                .UpdateAsync(user);

然而,现在的问题是我无法首先使用用户的旧密码来验证它,因为它只需要一个新密码并更新它。有什么想法吗?

编辑 2:在尝试使用获取用户令牌的第二种方法并在“v1.0/me/changePassword/”端点请求它时,通过邮递员尝试并获得“x5t 无效”后,我能够找到此回复here

“不幸的是,B2C 租户不支持这种重置密码的方法,因为 B2C 租户的 Graph API 中没有包含 UserAuthenticationMethod.ReadWrite.all 权限。B2C 租户中唯一可用的委派权限是 offline_access 和 openID。可用于在 B2C 租户中重置密码的方法是管理员通过 Azure 门户执行密码重置或使用密码重置策略。

截至目前,仅标准 Azure AD 租户支持通过 Graph API 重置密码。您可以在我们的反馈门户中发布有关 B2C 租户中此功能的想法。”

所以我猜测我以某种方式能够使用图形 API 更改上面的密码配置文件的事实不应该发生?

1 个答案:

答案 0 :(得分:0)

<块引用>

B2C 租户中唯一可用的委派权限是 offline_access 和 openID。

这不是真的。

要调用 Microsoft Graph API,您必须使用 AAD auth flow 而不是 AAD B2C 身份验证流程。因此,您无需使用与 b2c 用户流使用的 AAD 应用程序相同的 AAD 应用程序(应用程序注册)。

您可以创建一个新的 AAD 应用,其类型为仅在此组织目录中的帐户(仅限您的 b2c 租户 - 单个租户)在任何组织目录中的帐户(任何 Azure AD 目录 -多租户)

然后,您可以将 Microsoft Graph 权限 UserAuthenticationMethod.ReadWrite.all 分配给它,并使用这个新的 AAD 应用生成访问令牌以调用 Microsoft Graph。

类型为任何身份提供者或组织目录中的帐户(用于使用用户流对用户进行身份验证)的 AAD 应用无法添加 Microsoft 委派权限。

我们可以在Microsoft Graph Explorer中成功调用POST https://graph.microsoft.com/v1.0/me/changePassword为B2C用户修改密码,这也证明了Microsoft Graph确实适用于B2C用户。

同理,用Update user修改密码也是可行的。

<块引用>

但是,现在的问题是我无法首先使用 用户的旧密码,因为它只需要一个新密码和更新 它。有什么想法吗?

我不太明白 can't first validate this using the user's old password 是什么意思。如果您需要调查此方向,请提供有关此问题的更多详细信息。

相关问题