Skip to content

Commit

Permalink
Merge pull request #14442 from abpframework/VerifyPasswordResetTokenA…
Browse files Browse the repository at this point in the history
…sync

Invalidate the token after changing the password.
  • Loading branch information
realLiangshiwei authored Oct 26, 2022
2 parents 220016a + 84d419f commit 0053226
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ public interface IAccountAppService : IApplicationService

Task SendPasswordResetCodeAsync(SendPasswordResetCodeDto input);

Task<bool> VerifyPasswordResetTokenAsync(VerifyPasswordResetTokenInput input);

Task ResetPasswordAsync(ResetPasswordDto input);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.ComponentModel.DataAnnotations;

namespace Volo.Abp.Account;

public class VerifyPasswordResetTokenInput
{
public Guid UserId { get; set; }

[Required]
public string ResetToken { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ public virtual async Task SendPasswordResetCodeAsync(SendPasswordResetCodeDto in
await AccountEmailer.SendPasswordResetLinkAsync(user, resetToken, input.AppName, input.ReturnUrl, input.ReturnUrlHash);
}

public virtual async Task<bool> VerifyPasswordResetTokenAsync(VerifyPasswordResetTokenInput input)
{
var user = await UserManager.GetByIdAsync(input.UserId);
return await UserManager.VerifyUserTokenAsync(
user,
UserManager.Options.Tokens.PasswordResetTokenProvider,
UserManager<IdentityUser>.ResetPasswordTokenPurpose,
input.ResetToken);
}

public virtual async Task ResetPasswordAsync(ResetPasswordDto input)
{
await IdentityOptions.SetAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ public virtual async Task SendPasswordResetCodeAsync(SendPasswordResetCodeDto in
});
}

public virtual async Task<bool> VerifyPasswordResetTokenAsync(VerifyPasswordResetTokenInput input)
{
return await RequestAsync<bool>(nameof(VerifyPasswordResetTokenAsync), new ClientProxyRequestTypeValue
{
{ typeof(VerifyPasswordResetTokenInput), input }
});
}

public virtual async Task ResetPasswordAsync(ResetPasswordDto input)
{
await RequestAsync(nameof(ResetPasswordAsync), new ClientProxyRequestTypeValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using Volo.Abp.Http.Modeling;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.ClientProxying;
using Volo.Abp.Identity;
using Volo.Abp.Account;

// ReSharper disable once CheckNamespace
namespace Volo.Abp.Account.ClientProxies;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"Volo.Abp.Account.AccountController": {
"controllerName": "Account",
"controllerGroupName": "Account",
"isRemoteService": true,
"apiVersion": null,
"type": "Volo.Abp.Account.AccountController",
"interfaces": [
{
Expand Down Expand Up @@ -88,6 +90,43 @@
"allowAnonymous": null,
"implementFrom": "Volo.Abp.Account.IAccountAppService"
},
"VerifyPasswordResetTokenAsyncByInput": {
"uniqueName": "VerifyPasswordResetTokenAsyncByInput",
"name": "VerifyPasswordResetTokenAsync",
"httpMethod": "POST",
"url": "api/account/verify-password-reset-token",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "Volo.Abp.Account.VerifyPasswordResetTokenInput, Volo.Abp.Account.Application.Contracts",
"type": "Volo.Abp.Account.VerifyPasswordResetTokenInput",
"typeSimple": "Volo.Abp.Account.VerifyPasswordResetTokenInput",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "input",
"name": "input",
"jsonName": null,
"type": "Volo.Abp.Account.VerifyPasswordResetTokenInput",
"typeSimple": "Volo.Abp.Account.VerifyPasswordResetTokenInput",
"isOptional": false,
"defaultValue": null,
"constraintTypes": null,
"bindingSourceId": "Body",
"descriptorName": ""
}
],
"returnValue": {
"type": "System.Boolean",
"typeSimple": "boolean"
},
"allowAnonymous": null,
"implementFrom": "Volo.Abp.Account.IAccountAppService"
},
"ResetPasswordAsyncByInput": {
"uniqueName": "ResetPasswordAsyncByInput",
"name": "ResetPasswordAsync",
Expand Down Expand Up @@ -130,6 +169,8 @@
"Volo.Abp.Account.Web.Areas.Account.Controllers.AccountController": {
"controllerName": "Account",
"controllerGroupName": "Login",
"isRemoteService": true,
"apiVersion": null,
"type": "Volo.Abp.Account.Web.Areas.Account.Controllers.AccountController",
"interfaces": [],
"actions": {
Expand Down Expand Up @@ -227,6 +268,8 @@
"Volo.Abp.Account.ProfileController": {
"controllerName": "Profile",
"controllerGroupName": "Profile",
"isRemoteService": true,
"apiVersion": null,
"type": "Volo.Abp.Account.ProfileController",
"interfaces": [
{
Expand Down Expand Up @@ -329,4 +372,4 @@
}
},
"types": {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ public virtual Task SendPasswordResetCodeAsync(SendPasswordResetCodeDto input)
return AccountAppService.SendPasswordResetCodeAsync(input);
}

[HttpPost]
[Route("verify-password-reset-token")]
public Task<bool> VerifyPasswordResetTokenAsync(VerifyPasswordResetTokenInput input)
{
return AccountAppService.VerifyPasswordResetTokenAsync(input);
}

[HttpPost]
[Route("reset-password")]
public virtual Task ResetPasswordAsync(ResetPasswordDto input)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
@page
@inject IHtmlLocalizer<AccountResource> L
@inject IHtmlLocalizer<IdentityResource> LI
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@using Volo.Abp.Identity.Localization
@model Volo.Abp.Account.Web.Pages.Account.ResetPasswordModel
@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout
<div class="card mt-3 shadow-sm rounded">
<div class="card-body p-5">
<h4>@L["ResetPassword"]</h4>
<form method="post">
<p>@L["ResetPassword_Information"]</p>
<abp-input asp-for="UserId"/>
<abp-input asp-for="ResetToken"/>
<abp-input asp-for="Password" autocomplete="new-password" />
<abp-input asp-for="ConfirmPassword" autocomplete="new-password" />
<a abp-button="Secondary" asp-page="./Login">@L["Cancel"]</a>
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/>
</form>
@if (Model.InvalidToken)
{
<div class="alert alert-danger">
@LI["Volo.Abp.Identity:InvalidToken"]
</div>
}
else
{
<form method="post">
<p>@L["ResetPassword_Information"]</p>
<abp-input asp-for="UserId"/>
<abp-input asp-for="ResetToken"/>
<abp-input asp-for="Password" autocomplete="new-password" />
<abp-input asp-for="ConfirmPassword" autocomplete="new-password" />
<a abp-button="Secondary" asp-page="./Login">@L["Cancel"]</a>
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/>
</form>
}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
Expand Down Expand Up @@ -43,9 +44,21 @@ public class ResetPasswordModel : AccountPageModel
[DisableAuditing]
public string ConfirmPassword { get; set; }

public virtual Task<IActionResult> OnGetAsync()
public bool InvalidToken { get; set; }

public virtual async Task<IActionResult> OnGetAsync()
{
return Task.FromResult<IActionResult>(Page());
ValidateModel();

InvalidToken = !await AccountAppService.VerifyPasswordResetTokenAsync(
new VerifyPasswordResetTokenInput
{
UserId = UserId,
ResetToken = ResetToken
}
);

return Page();
}

public virtual async Task<IActionResult> OnPostAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,67 +5,75 @@

(function(){

// controller volo.abp.account.web.areas.account.controllers.account
// controller volo.abp.account.account

(function(){

abp.utils.createNamespace(window, 'volo.abp.account.web.areas.account.controllers.account');
abp.utils.createNamespace(window, 'volo.abp.account.account');

volo.abp.account.web.areas.account.controllers.account.login = function(login, ajaxParams) {
volo.abp.account.account.register = function(input, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/account/login',
url: abp.appPath + 'api/account/register',
type: 'POST',
data: JSON.stringify(login)
data: JSON.stringify(input)
}, ajaxParams));
};

volo.abp.account.web.areas.account.controllers.account.logout = function(ajaxParams) {
volo.abp.account.account.sendPasswordResetCode = function(input, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/account/logout',
type: 'GET',
dataType: null
url: abp.appPath + 'api/account/send-password-reset-code',
type: 'POST',
dataType: null,
data: JSON.stringify(input)
}, ajaxParams));
};

volo.abp.account.web.areas.account.controllers.account.checkPassword = function(login, ajaxParams) {
volo.abp.account.account.verifyPasswordResetToken = function(input, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/account/check-password',
url: abp.appPath + 'api/account/verify-password-reset-token',
type: 'POST',
data: JSON.stringify(login)
data: JSON.stringify(input)
}, ajaxParams));
};

volo.abp.account.account.resetPassword = function(input, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/account/reset-password',
type: 'POST',
dataType: null,
data: JSON.stringify(input)
}, ajaxParams));
};

})();

// controller volo.abp.account.account
// controller volo.abp.account.web.areas.account.controllers.account

(function(){

abp.utils.createNamespace(window, 'volo.abp.account.account');
abp.utils.createNamespace(window, 'volo.abp.account.web.areas.account.controllers.account');

volo.abp.account.account.register = function(input, ajaxParams) {
volo.abp.account.web.areas.account.controllers.account.login = function(login, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/account/register',
url: abp.appPath + 'api/account/login',
type: 'POST',
data: JSON.stringify(input)
data: JSON.stringify(login)
}, ajaxParams));
};

volo.abp.account.account.sendPasswordResetCode = function(input, ajaxParams) {
volo.abp.account.web.areas.account.controllers.account.logout = function(ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/account/send-password-reset-code',
type: 'POST',
dataType: null,
data: JSON.stringify(input)
url: abp.appPath + 'api/account/logout',
type: 'GET',
dataType: null
}, ajaxParams));
};

volo.abp.account.account.resetPassword = function(input, ajaxParams) {
volo.abp.account.web.areas.account.controllers.account.checkPassword = function(login, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/account/reset-password',
url: abp.appPath + 'api/account/check-password',
type: 'POST',
dataType: null,
data: JSON.stringify(input)
data: JSON.stringify(login)
}, ajaxParams));
};

Expand Down

0 comments on commit 0053226

Please sign in to comment.