hi
Remote debug will be hard.
Can you test your case in a new template project?
Thanks.
You can try the latest version:
Add a 2FA.cshtml
in your Pages
folder. Also, make it an embedded file.
Send an email to liming.ma@volosoft.com. I will share the 2FA.cshtml
content.
<ItemGroup>
<Content Remove="Pages\2FA.cshtml" />
<EmbeddedResource Include="Pages\2FA.cshtml" />
</ItemGroup>
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<ProfileManagementPageOptions>(options =>
{
options.Contributors.RemoveAll(x => x is AccountProfileManagementPageContributor);
options.Contributors.Add(new MyAccountProfileManagementPageContributor());
});
}
```cs System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.Account;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Public.Web.Pages.Account.Components.ProfileManagementGroup.TwoFactor;
using Volo.Abp.Account.Public.Web.ProfileManagement;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Identity;
using Volo.Abp.Identity.Settings;
using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Threading;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace MyCompanyName.MyProjectName.Web;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(AccountProfileTwoFactorManagementGroupViewComponent))]
public class MyAccountProfileTwoFactorManagementGroupViewComponent : AccountProfileTwoFactorManagementGroupViewComponent
{
public MyAccountProfileTwoFactorManagementGroupViewComponent(
IProfileAppService profileAppService,
IAccountAppService accountAppService,
IdentityProTwoFactorManager identityProTwoFactorManager)
: base(profileAppService, accountAppService, identityProTwoFactorManager)
{
}
public override async Task<IViewComponentResult> InvokeAsync()
{
var authenticatorInfo = await AccountAppService.GetAuthenticatorInfoAsync();
var model = new ChangeTwoFactorModel
{
TwoFactorForcedEnabled = await IdentityProTwoFactorManager.IsForcedEnableAsync(),
TwoFactorEnabled = await ProfileAppService.GetTwoFactorEnabledAsync(),
HasAuthenticator = await AccountAppService.HasAuthenticatorAsync(),
SharedKey = authenticatorInfo.Key,
AuthenticatorUri = authenticatorInfo.Uri
};
return View("~/Pages/2FA.cshtml", model);
}
}
public class MyAccountProfileManagementPageContributor : IProfileManagementPageContributor
{
public async Task ConfigureAsync(ProfileManagementPageCreationContext context)
{
await new AccountProfileManagementPageContributor().ConfigureAsync(context);
var identityTwoFactorManager = context.ServiceProvider.GetRequiredService<IdentityProTwoFactorManager>();
var settingProvider = context.ServiceProvider.GetRequiredService<ISettingProvider>();
if (!await identityTwoFactorManager.IsForcedDisableAsync() &&
await settingProvider.GetAsync<bool>(IdentityProSettingNames.TwoFactor.UsersCanChange))
{
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<AccountResource>>();
context.Groups.Add(
new ProfileManagementPageGroup(
"Volo-Abp-Account-TwoFactor",
l["ProfileTab:TwoFactor"],
typeof(AccountProfileTwoFactorManagementGroupViewComponent)
)
);
}
}
}
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IdentityUserManager))]
public class MyIdentityUserManager : IdentityUserManager
{
public MyIdentityUserManager(IdentityUserStore store,
IIdentityRoleRepository roleRepository,
IIdentityUserRepository userRepository,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityUser> passwordHasher,
IEnumerable<IUserValidator<IdentityUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<IdentityUserManager> logger,
ICancellationTokenProvider cancellationTokenProvider,
IOrganizationUnitRepository organizationUnitRepository,
ISettingProvider settingProvider,
IDistributedEventBus distributedEventBus,
IIdentityLinkUserRepository identityLinkUserRepository,
IDistributedCache<AbpDynamicClaimCacheItem> dynamicClaimCache)
: base(store, roleRepository, userRepository, optionsAccessor, passwordHasher, userValidators,
passwordValidators, keyNormalizer, errors, services, logger, cancellationTokenProvider,
organizationUnitRepository, settingProvider, distributedEventBus, identityLinkUserRepository,
dynamicClaimCache)
{
}
public override async Task<IList<string>> GetValidTwoFactorProvidersAsync(IdentityUser user)
{
var providers = await base.GetValidTwoFactorProvidersAsync(user);
providers.RemoveAll(x => x == TokenOptions.DefaultEmailProvider || x == TokenOptions.DefaultPhoneProvider);
return providers;
}
}
hi
Add the code below to your Blazor project will fix it.
var valueValidatorFactoryOptions = context.Services.ExecutePreConfiguredActions<ValueValidatorFactoryOptions>();
Configure<JsonOptions>(options =>
{
options.JsonSerializerOptions.Converters.AddIfNotContains(new StringValueTypeJsonConverter(valueValidatorFactoryOptions));
});
Does the /Account/Manage
page work?
Can you set up an authenticator?
Your account shouldn't enable 2FA without none provider
Thanks.
Which page? Please share a screenshot?
Does the /Account/Manage
page work?
Can you add a breakpoint to see the values of return providers
?
Thanks.
Thanks. I will check and fix it.
Great
hi
Try this version:
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IdentityUserManager))]
public class MyIdentityUserManager : IdentityUserManager
{
public MyIdentityUserManager(IdentityUserStore store,
IIdentityRoleRepository roleRepository,
IIdentityUserRepository userRepository,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityUser> passwordHasher,
IEnumerable<IUserValidator<IdentityUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<IdentityUserManager> logger,
ICancellationTokenProvider cancellationTokenProvider,
IOrganizationUnitRepository organizationUnitRepository,
ISettingProvider settingProvider,
IDistributedEventBus distributedEventBus,
IIdentityLinkUserRepository identityLinkUserRepository,
IDistributedCache<AbpDynamicClaimCacheItem> dynamicClaimCache)
: base(store, roleRepository, userRepository, optionsAccessor, passwordHasher, userValidators,
passwordValidators, keyNormalizer, errors, services, logger, cancellationTokenProvider,
organizationUnitRepository, settingProvider, distributedEventBus, identityLinkUserRepository,
dynamicClaimCache)
{
}
public override async Task<IList<string>> GetValidTwoFactorProvidersAsync(IdentityUser user)
{
var providers = await base.GetValidTwoFactorProvidersAsync(user);
providers.RemoveAll(x => x == TokenOptions.DefaultEmailProvider || x == TokenOptions.DefaultPhoneProvider);
if (!providers.Contains(TokenOptions.DefaultAuthenticatorProvider))
{
await Store.As<IUserAuthenticatorKeyStore<IdentityUser>>().SetAuthenticatorKeyAsync(user, GenerateNewAuthenticatorKey(), CancellationToken.None);
user.SetAuthenticator(true);
providers.Add(TokenOptions.DefaultAuthenticatorProvider);
}
return providers;
}
}