|
|
|
@ -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
|
|
|
|
|