diff --git a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs index 0d803c26e5..50dc7d06f8 100644 --- a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs +++ b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Models.Identity Culture = Configuration.GlobalSettings.DefaultUILanguage; } - public virtual async Task GenerateUserIdentityAsync(BackOfficeUserManager manager) + public virtual async Task GenerateUserIdentityAsync(BackOfficeUserManager manager) { // NOTE the authenticationType must match the umbraco one // defined in CookieAuthenticationOptions.AuthenticationType diff --git a/src/Umbraco.Core/Security/BackOfficeClaimsIdentityFactory.cs b/src/Umbraco.Core/Security/BackOfficeClaimsIdentityFactory.cs index 9c46ae69f4..7c2373a000 100644 --- a/src/Umbraco.Core/Security/BackOfficeClaimsIdentityFactory.cs +++ b/src/Umbraco.Core/Security/BackOfficeClaimsIdentityFactory.cs @@ -7,7 +7,8 @@ using Umbraco.Core.Models.Identity; namespace Umbraco.Core.Security { - public class BackOfficeClaimsIdentityFactory : ClaimsIdentityFactory + public class BackOfficeClaimsIdentityFactory : ClaimsIdentityFactory + where T: BackOfficeIdentityUser { public BackOfficeClaimsIdentityFactory() { @@ -20,7 +21,7 @@ namespace Umbraco.Core.Security /// /// /// - public override async Task CreateAsync(UserManager manager, BackOfficeIdentityUser user, string authenticationType) + public override async Task CreateAsync(UserManager manager, T user, string authenticationType) { var baseIdentity = await base.CreateAsync(manager, user, authenticationType); @@ -42,4 +43,9 @@ namespace Umbraco.Core.Security return umbracoIdentity; } } + + public class BackOfficeClaimsIdentityFactory : BackOfficeClaimsIdentityFactory + { + + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Security/BackOfficeSignInManager.cs b/src/Umbraco.Core/Security/BackOfficeSignInManager.cs index b36cd585df..7c65b43291 100644 --- a/src/Umbraco.Core/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Core/Security/BackOfficeSignInManager.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Security public override Task CreateUserIdentityAsync(BackOfficeIdentityUser user) { - return user.GenerateUserIdentityAsync((BackOfficeUserManager)UserManager); + return user.GenerateUserIdentityAsync((BackOfficeUserManager)UserManager); } public static BackOfficeSignInManager Create(IdentityFactoryOptions options, IOwinContext context, ILogger logger) diff --git a/src/Umbraco.Core/Security/BackOfficeUserManager.cs b/src/Umbraco.Core/Security/BackOfficeUserManager.cs index 8421d7f90c..2b68fd07eb 100644 --- a/src/Umbraco.Core/Security/BackOfficeUserManager.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserManager.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using System.Web.Security; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin.Security.DataProtection; using Umbraco.Core.Models.Identity; using Umbraco.Core.Services; @@ -70,7 +71,7 @@ namespace Umbraco.Core.Security { var manager = new BackOfficeUserManager(customUserStore, options, membershipProvider); return manager; - } + } #endregion /// @@ -80,65 +81,15 @@ namespace Umbraco.Core.Security /// /// /// - protected void InitUserManager(BackOfficeUserManager manager, MembershipProviderBase membershipProvider, IdentityFactoryOptions options) + protected void InitUserManager( + BackOfficeUserManager manager, + MembershipProviderBase membershipProvider, + IdentityFactoryOptions options) { - // Configure validation logic for usernames - manager.UserValidator = new UserValidator(manager) - { - AllowOnlyAlphanumericUserNames = false, - RequireUniqueEmail = true - }; - - // Configure validation logic for passwords - manager.PasswordValidator = new PasswordValidator - { - RequiredLength = membershipProvider.MinRequiredPasswordLength, - RequireNonLetterOrDigit = membershipProvider.MinRequiredNonAlphanumericCharacters > 0, - RequireDigit = false, - RequireLowercase = false, - RequireUppercase = false - //TODO: Do we support the old regex match thing that membership providers used? - }; - - //use a custom hasher based on our membership provider - manager.PasswordHasher = new MembershipPasswordHasher(membershipProvider); - - var dataProtectionProvider = options.DataProtectionProvider; - if (dataProtectionProvider != null) - { - manager.UserTokenProvider = new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); - } - - manager.UserLockoutEnabledByDefault = true; - manager.MaxFailedAccessAttemptsBeforeLockout = membershipProvider.MaxInvalidPasswordAttempts; - //NOTE: This just needs to be in the future, we currently don't support a lockout timespan, it's either they are locked - // or they are not locked, but this determines what is set on the account lockout date which corresponds to whether they are - // locked out or not. - manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromDays(30); - - //custom identity factory for creating the identity object for which we auth against in the back office - manager.ClaimsIdentityFactory = new BackOfficeClaimsIdentityFactory(); - - manager.EmailService = new EmailService(); - - //NOTE: Not implementing these, if people need custom 2 factor auth, they'll need to implement their own UserStore to suport it - - //// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user - //// You can write your own provider and plug in here. - //manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider - //{ - // MessageFormat = "Your security code is: {0}" - //}); - //manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider - //{ - // Subject = "Security Code", - // BodyFormat = "Your security code is: {0}" - //}); - - //manager.SmsService = new SmsService(); + //NOTE: This method is mostly here for backwards compat + base.InitUserManager(manager, membershipProvider, options.DataProtectionProvider); } - } /// @@ -181,6 +132,73 @@ namespace Umbraco.Core.Security } #endregion + /// + /// Initializes the user manager with the correct options + /// + /// + /// + /// + /// + protected void InitUserManager( + BackOfficeUserManager manager, + MembershipProviderBase membershipProvider, + IDataProtectionProvider dataProtectionProvider) + { + // Configure validation logic for usernames + manager.UserValidator = new UserValidator(manager) + { + AllowOnlyAlphanumericUserNames = false, + RequireUniqueEmail = true + }; + + // Configure validation logic for passwords + manager.PasswordValidator = new PasswordValidator + { + RequiredLength = membershipProvider.MinRequiredPasswordLength, + RequireNonLetterOrDigit = membershipProvider.MinRequiredNonAlphanumericCharacters > 0, + RequireDigit = false, + RequireLowercase = false, + RequireUppercase = false + //TODO: Do we support the old regex match thing that membership providers used? + }; + + //use a custom hasher based on our membership provider + manager.PasswordHasher = new MembershipPasswordHasher(membershipProvider); + + if (dataProtectionProvider != null) + { + manager.UserTokenProvider = new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); + } + + manager.UserLockoutEnabledByDefault = true; + manager.MaxFailedAccessAttemptsBeforeLockout = membershipProvider.MaxInvalidPasswordAttempts; + //NOTE: This just needs to be in the future, we currently don't support a lockout timespan, it's either they are locked + // or they are not locked, but this determines what is set on the account lockout date which corresponds to whether they are + // locked out or not. + manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromDays(30); + + //custom identity factory for creating the identity object for which we auth against in the back office + manager.ClaimsIdentityFactory = new BackOfficeClaimsIdentityFactory(); + + manager.EmailService = new EmailService(); + + //NOTE: Not implementing these, if people need custom 2 factor auth, they'll need to implement their own UserStore to suport it + + //// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user + //// You can write your own provider and plug in here. + //manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider + //{ + // MessageFormat = "Your security code is: {0}" + //}); + //manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider + //{ + // Subject = "Security Code", + // BodyFormat = "Your security code is: {0}" + //}); + + //manager.SmsService = new SmsService(); + } + /// /// Logic used to validate a username and password ///