Search code examples
c#asp.net-coresettingsaspnetboilerplateasp.net-core-identity

How to set up TwoFactor and Lockout settings with ASP.NET Boilerplate templates?


I've been using ASP.NET Boilerplate as a template for my application as a starting point. I was in the process of modifying the login process to implement 2FA. However, I'm not sure where to put those configuration settings. In a previous application using .NET MVC with .NET Identity, I was able to do this in a class we had as ApplicationUserManager that inherited UserManager. This is how I had things configured:

public class ApplicationUserManager : UserManager<User>
{
    public ApplicationUserManager(IUserStore<User> store) : base(store)
    {
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<User>(context.Get<Db>()));
        // Configure validation logic for usernames
        manager.UserValidator = new UserValidator<User>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        // Configure user lockout defaults
        manager.UserLockoutEnabledByDefault = true;
        manager.MaxFailedAccessAttemptsBeforeLockout = 5;
        manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromDays(365*500);

        manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<User>()
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is: {0}"
        });

        manager.EmailService = new EmailService();

        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<User>(dataProtectionProvider.Create("ASP.NET Identity"));
        }

        return manager;
    }
}

In ASP.NET Boilerplate, there are a lot of powerful tools and many interfaces that can be implemented to assist in the login process. I've seen a GitHub post where disable lockout feature was discussed, and it looks like I should be able to add to my SettingsManager database options for MaxFailedAccessAttempts and DefaultLockoutTimeSpan, but I'm not sure that just by adding them to the database that they will be picked up auto-magically, especially if I do not name them correctly. There is already a class of constant values for EmailSettings that I was able to use here:

public void Create()
{
    // Emailing
    AddSettingIfNotExists(EmailSettingNames.DefaultFromAddress, "developer@developer.com");
    AddSettingIfNotExists(EmailSettingNames.DefaultFromDisplayName, "do not reply");
    AddSettingIfNotExists(EmailSettingNames.Smtp.Host, "smtp.gmail.com");
    AddSettingIfNotExists(EmailSettingNames.Smtp.Port, "587");
    AddSettingIfNotExists(EmailSettingNames.Smtp.UserName, "developer@developer.com");
    AddSettingIfNotExists(EmailSettingNames.Smtp.Password, "SomePassword");
    AddSettingIfNotExists(EmailSettingNames.Smtp.EnableSsl, "true");
    AddSettingIfNotExists(EmailSettingNames.Smtp.UseDefaultCredentials, "false");

    // Languages
    AddSettingIfNotExists(LocalizationSettingNames.DefaultLanguage, "en");
}

There is also a class in the Core project — AppSettingNames, which contains a value for UiTheme. I suppose I can add the constant values there. However, if I do this, do I need to name these settings identically to what the UserManager attributes are looking for?


Solution

  • The relevant constants are in AbpZeroSettingNames.

    // DefaultLockoutTimeSpan
    AddSettingIfNotExists(
        AbpZeroSettingNames.UserManagement.UserLockOut.DefaultAccountLockoutSeconds,
        int.MaxValue.ToString() // 2,147,483,647 seconds, just over 68 years
    );
    
    // MaxFailedAccessAttempts
    AddSettingIfNotExists(
        AbpZeroSettingNames.UserManagement.UserLockOut.MaxFailedAccessAttemptsBeforeLockout,
        "5"
    );
    

    Unfortunately, int.MaxValue in seconds only allows the application to lock out the user for just over 68 years at a time, shy of the 500 years that you used to configure.