Browse Source

Return `changePasswordToken` for angular.

pull/15708/head
maliming 3 years ago
parent
commit
877d3d59ac
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 58
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs
  2. 83
      modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs

58
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs

@ -125,7 +125,7 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
if (user.ShouldChangePasswordOnNextLogin)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, nameof(user.ShouldChangePasswordOnNextLogin));
await HandleShouldChangePasswordOnNextLoginAsync(context, user);
return;
}
@ -200,6 +200,62 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
}
}
protected virtual async Task HandleShouldChangePasswordOnNextLoginAsync(ResourceOwnerPasswordValidationContext context, IdentityUser user)
{
var changePasswordToken = context.Request?.Raw?["ChangePasswordToken"];
var currentPassword = context.Request?.Raw?["CurrentPassword"];
var newPassword = context.Request?.Raw?["NewPassword"];
if (!changePasswordToken.IsNullOrWhiteSpace() && !currentPassword.IsNullOrWhiteSpace() && !newPassword.IsNullOrWhiteSpace())
{
if (await UserManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, nameof(IdentityUser.ShouldChangePasswordOnNextLogin), changePasswordToken))
{
var changePasswordResult = await UserManager.ChangePasswordAsync(user, currentPassword, newPassword);
if (changePasswordResult.Succeeded)
{
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = IdentitySecurityLogActionConsts.ChangePassword,
UserName = context.UserName,
ClientId = await FindClientIdAsync(context)
});
user.SetShouldChangePasswordOnNextLogin(false);
await UserManager.UpdateAsync(user);
await SetSuccessResultAsync(context, user);
}
else
{
Logger.LogInformation("ChangePassword failed for username: {username}, reason: {changePasswordResult}", context.UserName, changePasswordResult);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, changePasswordResult.Errors.Select(x => x.Description).JoinAsString(", "));
}
}
else
{
Logger.LogInformation("Authentication failed for username: {username}, reason: InvalidAuthenticatorCode", context.UserName);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, Localizer["InvalidAuthenticatorCode"]);
}
}
else
{
Logger.LogInformation("Authentication failed for username: {username}, reason: {ShouldChangePasswordOnNextLogin}", context.UserName, nameof(user.ShouldChangePasswordOnNextLogin));
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, nameof(user.ShouldChangePasswordOnNextLogin),
new Dictionary<string, object>()
{
{"userId", user.Id},
{"changePasswordToken", await UserManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, nameof(IdentityUser.ShouldChangePasswordOnNextLogin))}
});
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = IdentityServerSecurityLogActionConsts.LoginNotAllowed,
UserName = context.UserName,
ClientId = await FindClientIdAsync(context)
});
}
}
protected virtual async Task SetSuccessResultAsync(ResourceOwnerPasswordValidationContext context, IdentityUser user)
{
var sub = await UserManager.GetUserIdAsync(user);

83
modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs

@ -104,11 +104,7 @@ public partial class TokenController
if (user.ShouldChangePasswordOnNextLogin)
{
return Forbid(
new AuthenticationProperties(items: new Dictionary<string, string> {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = nameof(user.ShouldChangePasswordOnNextLogin)
}), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
return await HandleShouldChangePasswordOnNextLoginAsync(request, user);
}
errorDescription = "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.";
@ -219,6 +215,83 @@ public partial class TokenController
}
}
protected virtual async Task<IActionResult> HandleShouldChangePasswordOnNextLoginAsync(OpenIddictRequest request, IdentityUser user)
{
var changePasswordToken = request.GetParameter("ChangePasswordToken")?.ToString();
var currentPassword = request.GetParameter("CurrentPassword")?.ToString();
var newPassword = request.GetParameter("NewPassword")?.ToString();
if (!changePasswordToken.IsNullOrWhiteSpace() && !currentPassword.IsNullOrWhiteSpace() && !newPassword.IsNullOrWhiteSpace())
{
if (await UserManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, nameof(IdentityUser.ShouldChangePasswordOnNextLogin), changePasswordToken))
{
var changePasswordResult = await UserManager.ChangePasswordAsync(user, currentPassword, newPassword);
if (changePasswordResult.Succeeded)
{
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{
Identity = OpenIddictSecurityLogIdentityConsts.OpenIddict,
Action = IdentitySecurityLogActionConsts.ChangePassword,
UserName = request.Username,
ClientId = request.ClientId
});
user.SetShouldChangePasswordOnNextLogin(false);
await UserManager.UpdateAsync(user);
return await SetSuccessResultAsync(request, user);
}
else
{
Logger.LogInformation("ChangePassword failed for username: {username}, reason: {changePasswordResult}", request.Username, changePasswordResult.Errors.Select(x => x.Description).JoinAsString(", "));
var properties = new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = changePasswordResult.Errors.Select(x => x.Description).JoinAsString(", ")
});
return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
}
else
{
Logger.LogInformation("Authentication failed for username: {username}, reason: InvalidAuthenticatorCode", request.Username);
var properties = new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "Invalid authenticator code!"
});
return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
}
else
{
Logger.LogInformation("Authentication failed for username: {username}, reason: {ShouldChangePasswordOnNextLogin}", request.Username, nameof(user.ShouldChangePasswordOnNextLogin));
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
{
Identity = OpenIddictSecurityLogIdentityConsts.OpenIddict,
Action = OpenIddictSecurityLogActionConsts.LoginNotAllowed,
UserName = request.Username,
ClientId = request.ClientId
});
var properties = new AuthenticationProperties(
items: new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = nameof(SignInResult.RequiresTwoFactor)
},
parameters: new Dictionary<string, object>
{
["userId"] = user.Id.ToString("N"),
["changePasswordToken"] = await UserManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, nameof(IdentityUser.ShouldChangePasswordOnNextLogin))
});
return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
}
protected virtual async Task<IActionResult> SetSuccessResultAsync(OpenIddictRequest request, IdentityUser user)
{
// Create a new ClaimsPrincipal containing the claims that

Loading…
Cancel
Save