Removes the explicit castings to (BackOfficeUserManager) since that isn't actually the base class! The base class is BackOfficeUserManager<BackOfficeIdentityUser>, all of this identity stuff is a bit of a generics nightmare but that also do to the generic nightmare that is OWIN. Moves more logic to the base class so it can be used by sub classes, fixes the base class to use a generic user type

This commit is contained in:
Shannon
2016-08-12 16:17:14 +02:00
parent 2ff3ce933b
commit 6bcadfea44
4 changed files with 85 additions and 61 deletions

View File

@@ -7,7 +7,8 @@ using Umbraco.Core.Models.Identity;
namespace Umbraco.Core.Security
{
public class BackOfficeClaimsIdentityFactory : ClaimsIdentityFactory<BackOfficeIdentityUser, int>
public class BackOfficeClaimsIdentityFactory<T> : ClaimsIdentityFactory<T, int>
where T: BackOfficeIdentityUser
{
public BackOfficeClaimsIdentityFactory()
{
@@ -20,7 +21,7 @@ namespace Umbraco.Core.Security
/// </summary>
/// <param name="manager"/><param name="user"/><param name="authenticationType"/>
/// <returns/>
public override async Task<ClaimsIdentity> CreateAsync(UserManager<BackOfficeIdentityUser, int> manager, BackOfficeIdentityUser user, string authenticationType)
public override async Task<ClaimsIdentity> CreateAsync(UserManager<T, int> 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<BackOfficeIdentityUser>
{
}
}

View File

@@ -29,7 +29,7 @@ namespace Umbraco.Core.Security
public override Task<ClaimsIdentity> CreateUserIdentityAsync(BackOfficeIdentityUser user)
{
return user.GenerateUserIdentityAsync((BackOfficeUserManager)UserManager);
return user.GenerateUserIdentityAsync((BackOfficeUserManager<BackOfficeIdentityUser>)UserManager);
}
public static BackOfficeSignInManager Create(IdentityFactoryOptions<BackOfficeSignInManager> options, IOwinContext context, ILogger logger)

View File

@@ -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
/// <summary>
@@ -80,65 +81,15 @@ namespace Umbraco.Core.Security
/// <param name="membershipProvider"></param>
/// <param name="options"></param>
/// <returns></returns>
protected void InitUserManager(BackOfficeUserManager manager, MembershipProviderBase membershipProvider, IdentityFactoryOptions<BackOfficeUserManager> options)
protected void InitUserManager(
BackOfficeUserManager manager,
MembershipProviderBase membershipProvider,
IdentityFactoryOptions<BackOfficeUserManager> options)
{
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<BackOfficeIdentityUser, int>(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<BackOfficeIdentityUser, int>(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<ApplicationUser>
//{
// MessageFormat = "Your security code is: {0}"
//});
//manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
//{
// 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);
}
}
/// <summary>
@@ -181,6 +132,73 @@ namespace Umbraco.Core.Security
}
#endregion
/// <summary>
/// Initializes the user manager with the correct options
/// </summary>
/// <param name="manager"></param>
/// <param name="membershipProvider"></param>
/// <param name="dataProtectionProvider"></param>
/// <returns></returns>
protected void InitUserManager(
BackOfficeUserManager<T> manager,
MembershipProviderBase membershipProvider,
IDataProtectionProvider dataProtectionProvider)
{
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<T, int>(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<T, int>(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<T>();
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<ApplicationUser>
//{
// MessageFormat = "Your security code is: {0}"
//});
//manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
//{
// Subject = "Security Code",
// BodyFormat = "Your security code is: {0}"
//});
//manager.SmsService = new SmsService();
}
/// <summary>
/// Logic used to validate a username and password
/// </summary>