From 649a1e2c6d07f5f9045a6aa21e05729c4f3c327d Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 22 Jun 2023 08:23:34 +0800 Subject: [PATCH 1/2] Support `RecoveryCode` login. --- .../Localization/Resources/en.json | 1 + .../Localization/Resources/tr.json | 3 ++- .../Localization/Resources/zh-Hans.json | 1 + .../Localization/Resources/zh-Hant.json | 3 ++- .../AbpResourceOwnerPasswordValidator.cs | 13 ++++++++++++ .../Controllers/TokenController.Password.cs | 20 ++++++++++++++++++- 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json index e756db2877..82d4be83b0 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/en.json @@ -10,6 +10,7 @@ "LoginIsNotAllowed": "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.", "InvalidUsername": "Invalid username or password!", "InvalidAuthenticatorCode": "Invalid authenticator code!", + "InvalidRecoveryCode": "Invalid recovery code!", "TheTargetUserIsNotLinkedToYou": "The target user is not linked to you!" } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json index ae1c958875..ef893f60ef 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/tr.json @@ -10,6 +10,7 @@ "LoginIsNotAllowed": "Giriş yapmanıza izin verilmiyor! Hesabınız etkin değil veya e-postanızı/telefon numaranızı onaylamanız gerekiyor.", "InvalidUsername": "Kullanıcı adı ya da şifre geçersiz!", "InvalidAuthenticatorCode": "Geçersiz kimlik doğrulama kodu!", + "InvalidRecoveryCode": "Geçersiz kurtarma kodu!", "TheTargetUserIsNotLinkedToYou": "Hedef kullanıcı sizinle bağlantılı değil!" } -} \ No newline at end of file +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json index 20bc8b43f0..a2d828bab2 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hans.json @@ -10,6 +10,7 @@ "LoginIsNotAllowed": "无法登录!你的账号未激活或者需要验证邮箱地址/手机号.", "InvalidUsername": "用户名或密码错误!", "InvalidAuthenticatorCode": "验证码无效!", + "InvalidRecoveryCode": "恢复代码无效!", "TheTargetUserIsNotLinkedToYou": "目标用户未和你有关联!" } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json index 42e7b0c27c..3678d6b572 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/zh-Hant.json @@ -10,6 +10,7 @@ "LoginIsNotAllowed": "無法登入!你的賬號未激活或者需要驗證郵箱地址/手機號碼.", "InvalidUsername": "用戶名或密碼錯誤!", "InvalidAuthenticatorCode": "驗證碼無效!", + "InvalidRecoveryCode": "恢復碼無效!", "TheTargetUserIsNotLinkedToYou": "目標用戶與您無關!" } -} \ No newline at end of file +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs index b2c7ebecb6..6e71e5d83a 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs @@ -178,6 +178,19 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator protected virtual async Task HandleTwoFactorLoginAsync(ResourceOwnerPasswordValidationContext context, IdentityUser user) { + var recoveryCode = context.Request?.Raw?["RecoveryCode"]; + if (!recoveryCode.IsNullOrWhiteSpace()) + { + var result = await UserManager.RedeemTwoFactorRecoveryCodeAsync(user, recoveryCode); + if (result.Succeeded) + { + await SetSuccessResultAsync(context, user); + } + + Logger.LogInformation("Authentication failed for username: {username}, reason: InvalidRecoveryCode", context.UserName); + context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, Localizer["InvalidRecoveryCode"]); + } + var twoFactorProvider = context.Request?.Raw?["TwoFactorProvider"]; var twoFactorCode = context.Request?.Raw?["TwoFactorCode"]; if (!twoFactorProvider.IsNullOrWhiteSpace() && !twoFactorCode.IsNullOrWhiteSpace()) diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs index a91745b519..33b01a7449 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs @@ -175,8 +175,26 @@ public partial class TokenController protected virtual async Task HandleTwoFactorLoginAsync(OpenIddictRequest request, IdentityUser user) { + var recoveryCode = request.GetParameter("RecoveryCode")?.ToString(); + if (!recoveryCode.IsNullOrWhiteSpace()) + { + var result = await UserManager.RedeemTwoFactorRecoveryCodeAsync(user, recoveryCode); + if (result.Succeeded) + { + return await SetSuccessResultAsync(request, user); + } + + var properties = new AuthenticationProperties(new Dictionary + { + [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant, + [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "Invalid recovery code!" + }); + + return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); + } + var twoFactorProvider = request.GetParameter("TwoFactorProvider")?.ToString(); - var twoFactorCode = request.GetParameter("TwoFactorCode")?.ToString();; + var twoFactorCode = request.GetParameter("TwoFactorCode")?.ToString(); if (!twoFactorProvider.IsNullOrWhiteSpace() && !twoFactorCode.IsNullOrWhiteSpace()) { var providers = await UserManager.GetValidTwoFactorProvidersAsync(user); From 0e79ced89ea36088950fef369769c5ab9981529d Mon Sep 17 00:00:00 2001 From: Engincan VESKE <43685404+EngincanV@users.noreply.github.com> Date: Thu, 22 Jun 2023 10:40:47 +0300 Subject: [PATCH 2/2] Update AbpResourceOwnerPasswordValidator.cs --- .../AspNetIdentity/AbpResourceOwnerPasswordValidator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs index 6e71e5d83a..628eb37cb7 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs @@ -185,6 +185,7 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator if (result.Succeeded) { await SetSuccessResultAsync(context, user); + return; } Logger.LogInformation("Authentication failed for username: {username}, reason: InvalidRecoveryCode", context.UserName);