diff --git a/src/Umbraco.Web/Models/Identity/IdentityUser.cs b/src/Umbraco.Core/Models/Identity/IdentityUser.cs
similarity index 98%
rename from src/Umbraco.Web/Models/Identity/IdentityUser.cs
rename to src/Umbraco.Core/Models/Identity/IdentityUser.cs
index 7bd077e879..093e42c1e7 100644
--- a/src/Umbraco.Web/Models/Identity/IdentityUser.cs
+++ b/src/Umbraco.Core/Models/Identity/IdentityUser.cs
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
-using Umbraco.Core.Models.Identity;
-namespace Umbraco.Web.Models.Identity
+namespace Umbraco.Core.Models.Identity
{
///
/// Default IUser implementation
diff --git a/src/Umbraco.Web/Security/BackOfficeClaimsPrincipalFactory.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeClaimsPrincipalFactory.cs
similarity index 95%
rename from src/Umbraco.Web/Security/BackOfficeClaimsPrincipalFactory.cs
rename to src/Umbraco.Infrastructure/BackOffice/BackOfficeClaimsPrincipalFactory.cs
index fe22981831..a463a84d4b 100644
--- a/src/Umbraco.Web/Security/BackOfficeClaimsPrincipalFactory.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeClaimsPrincipalFactory.cs
@@ -4,10 +4,9 @@ using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
-using Umbraco.Core.Security;
-using Umbraco.Web.Models.Identity;
+using Umbraco.Core.BackOffice;
-namespace Umbraco.Web.Security
+namespace Umbraco.Core.BackOffice
{
public class BackOfficeClaimsPrincipalFactory : UserClaimsPrincipalFactory
where TUser : BackOfficeIdentityUser
diff --git a/src/Umbraco.Web/Models/Identity/BackOfficeIdentityUser.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeIdentityUser.cs
similarity index 98%
rename from src/Umbraco.Web/Models/Identity/BackOfficeIdentityUser.cs
rename to src/Umbraco.Infrastructure/BackOffice/BackOfficeIdentityUser.cs
index 21c965aa3d..ea160ef1cf 100644
--- a/src/Umbraco.Web/Models/Identity/BackOfficeIdentityUser.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeIdentityUser.cs
@@ -4,13 +4,12 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
-using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.Identity;
using Umbraco.Core.Models.Membership;
-namespace Umbraco.Web.Models.Identity
+namespace Umbraco.Core.BackOffice
{
public class BackOfficeIdentityUser : IdentityUser, IdentityUserClaim>, IRememberBeingDirty
{
@@ -90,8 +89,8 @@ namespace Umbraco.Web.Models.Identity
///
public bool HasIdentity => _hasIdentity;
- public int[] CalculatedMediaStartNodeIds { get; internal set; }
- public int[] CalculatedContentStartNodeIds { get; internal set; }
+ public int[] CalculatedMediaStartNodeIds { get; set; }
+ public int[] CalculatedContentStartNodeIds { get; set; }
public override int Id
{
@@ -258,7 +257,7 @@ namespace Umbraco.Web.Models.Identity
///
/// Based on the user's lockout end date, this will determine if they are locked out
///
- internal bool IsLockedOut
+ public bool IsLockedOut
{
get
{
@@ -270,7 +269,7 @@ namespace Umbraco.Web.Models.Identity
///
/// This is a 1:1 mapping with IUser.IsApproved
///
- internal bool IsApproved { get; set; }
+ public bool IsApproved { get; set; }
///
/// Overridden to make the retrieval lazy
diff --git a/src/Umbraco.Web/Security/BackOfficeUserManager.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserManager.cs
similarity index 70%
rename from src/Umbraco.Web/Security/BackOfficeUserManager.cs
rename to src/Umbraco.Infrastructure/BackOffice/BackOfficeUserManager.cs
index a143029327..b98a9bb68c 100644
--- a/src/Umbraco.Web/Security/BackOfficeUserManager.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserManager.cs
@@ -1,143 +1,42 @@
-using System;
+using System;
using System.Collections.Generic;
-using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
-using Microsoft.Owin.Security.DataProtection;
-using Umbraco.Core;
using Umbraco.Core.Configuration;
-using Umbraco.Core.Mapping;
using Umbraco.Core.Security;
-using Umbraco.Core.Services;
using Umbraco.Net;
-using Umbraco.Web.Models.Identity;
-namespace Umbraco.Web.Security
+namespace Umbraco.Core.BackOffice
{
public class BackOfficeUserManager : BackOfficeUserManager
{
- public const string OwinMarkerKey = "Umbraco.Web.Security.Identity.BackOfficeUserManagerMarker";
-
- public BackOfficeUserManager(
- IPasswordConfiguration passwordConfiguration,
- IIpResolver ipResolver,
- IUserStore store,
- IOptions optionsAccessor,
- IEnumerable> userValidators,
- IEnumerable> passwordValidators,
- ILookupNormalizer keyNormalizer,
- IdentityErrorDescriber errors,
- IDataProtectionProvider dataProtectionProvider,
- ILogger> logger)
- : base(passwordConfiguration, ipResolver, store, optionsAccessor, userValidators, passwordValidators, keyNormalizer, errors, null, logger)
+ public BackOfficeUserManager(IIpResolver ipResolver, IUserStore store, IOptions optionsAccessor, IPasswordHasher passwordHasher, IEnumerable> userValidators, IEnumerable> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger> logger)
+ : base(ipResolver, store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
- InitUserManager(this, dataProtectionProvider);
}
-
- #region Static Create methods
-
- ///
- /// Creates a BackOfficeUserManager instance with all default options and the default BackOfficeUserManager
- ///
- public static BackOfficeUserManager Create(
- IUserService userService,
- IEntityService entityService,
- IExternalLoginService externalLoginService,
- IGlobalSettings globalSettings,
- UmbracoMapper mapper,
- IPasswordConfiguration passwordConfiguration,
- IIpResolver ipResolver,
- IdentityErrorDescriber errors,
- IDataProtectionProvider dataProtectionProvider,
- ILogger> logger)
- {
- var store = new BackOfficeUserStore(userService, entityService, externalLoginService, globalSettings, mapper);
-
- return Create(
- passwordConfiguration,
- ipResolver,
- store,
- errors,
- dataProtectionProvider,
- logger);
- }
-
- ///
- /// Creates a BackOfficeUserManager instance with all default options and a custom BackOfficeUserManager instance
- ///
- public static BackOfficeUserManager Create(
- IPasswordConfiguration passwordConfiguration,
- IIpResolver ipResolver,
- IUserStore customUserStore,
- IdentityErrorDescriber errors,
- IDataProtectionProvider dataProtectionProvider,
- ILogger> logger)
- {
- var options = new IdentityOptions();
-
- // Configure validation logic for usernames
- var userValidators = new List> { new BackOfficeUserValidator() };
- options.User.RequireUniqueEmail = true;
-
- // Configure validation logic for passwords
- var passwordValidators = new List> { new PasswordValidator() };
- options.Password.RequiredLength = passwordConfiguration.RequiredLength;
- options.Password.RequireNonAlphanumeric = passwordConfiguration.RequireNonLetterOrDigit;
- options.Password.RequireDigit = passwordConfiguration.RequireDigit;
- options.Password.RequireLowercase = passwordConfiguration.RequireLowercase;
- options.Password.RequireUppercase = passwordConfiguration.RequireUppercase;
-
- // Ensure Umbraco security stamp claim type is used
- options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier;
- options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
- options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role;
- options.ClaimsIdentity.SecurityStampClaimType = Constants.Web.SecurityStampClaimType;
-
- options.Lockout.AllowedForNewUsers = true;
- options.Lockout.MaxFailedAccessAttempts = passwordConfiguration.MaxFailedAccessAttemptsBeforeLockout;
- //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.
- options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromDays(30);
-
- return new BackOfficeUserManager(
- passwordConfiguration,
- ipResolver,
- customUserStore,
- new OptionsWrapper(options),
- userValidators,
- passwordValidators,
- new NopLookupNormalizer(),
- errors,
- dataProtectionProvider,
- logger);
- }
-
- #endregion
}
public class BackOfficeUserManager : UserManager
where T : BackOfficeIdentityUser
{
private PasswordGenerator _passwordGenerator;
-
+
public BackOfficeUserManager(
- IPasswordConfiguration passwordConfiguration,
IIpResolver ipResolver,
IUserStore store,
IOptions optionsAccessor,
+ IPasswordHasher passwordHasher,
IEnumerable> userValidators,
IEnumerable> passwordValidators,
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger> logger)
- : base(store, optionsAccessor, null, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
+ : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
- PasswordConfiguration = passwordConfiguration ?? throw new ArgumentNullException(nameof(passwordConfiguration));
IpResolver = ipResolver ?? throw new ArgumentNullException(nameof(ipResolver));
}
@@ -157,33 +56,6 @@ namespace Umbraco.Web.Security
public override bool SupportsUserPhoneNumber => false;
#endregion
- ///
- /// Initializes the user manager with the correct options
- ///
- protected void InitUserManager(
- BackOfficeUserManager manager,
- IDataProtectionProvider dataProtectionProvider)
- {
- // use a custom hasher based on our membership provider
- PasswordHasher = GetDefaultPasswordHasher(PasswordConfiguration);
-
- // set OWIN data protection token provider as default
- if (dataProtectionProvider != null)
- {
- manager.RegisterTokenProvider(
- TokenOptions.DefaultProvider,
- new OwinDataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity"))
- {
- TokenLifespan = TimeSpan.FromDays(3)
- });
- }
-
- // register ASP.NET Core Identity token providers
- manager.RegisterTokenProvider(TokenOptions.DefaultEmailProvider, new EmailTokenProvider());
- manager.RegisterTokenProvider(TokenOptions.DefaultPhoneProvider, new PhoneNumberTokenProvider());
- manager.RegisterTokenProvider(TokenOptions.DefaultAuthenticatorProvider, new AuthenticatorTokenProvider());
- }
-
///
/// Used to validate a user's session
///
@@ -206,14 +78,14 @@ namespace Umbraco.Web.Security
protected virtual IPasswordHasher GetDefaultPasswordHasher(IPasswordConfiguration passwordConfiguration)
{
//we can use the user aware password hasher (which will be the default and preferred way)
- return new UserAwarePasswordHasher(new PasswordSecurity(passwordConfiguration));
+ return new PasswordHasher();
}
///
/// Gets/sets the default back office user password checker
///
public IBackOfficeUserPasswordChecker BackOfficeUserPasswordChecker { get; set; }
- public IPasswordConfiguration PasswordConfiguration { get; }
+ public IPasswordConfiguration PasswordConfiguration { get; protected set; }
public IIpResolver IpResolver { get; }
///
@@ -457,57 +329,57 @@ namespace Umbraco.Web.Security
return result;
}
- internal void RaiseAccountLockedEvent(int userId)
+ public void RaiseAccountLockedEvent(int userId)
{
OnAccountLocked(new IdentityAuditEventArgs(AuditEvent.AccountLocked, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaiseAccountUnlockedEvent(int userId)
+ public void RaiseAccountUnlockedEvent(int userId)
{
OnAccountUnlocked(new IdentityAuditEventArgs(AuditEvent.AccountUnlocked, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaiseForgotPasswordRequestedEvent(int userId)
+ public void RaiseForgotPasswordRequestedEvent(int userId)
{
OnForgotPasswordRequested(new IdentityAuditEventArgs(AuditEvent.ForgotPasswordRequested, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaiseForgotPasswordChangedSuccessEvent(int userId)
+ public void RaiseForgotPasswordChangedSuccessEvent(int userId)
{
OnForgotPasswordChangedSuccess(new IdentityAuditEventArgs(AuditEvent.ForgotPasswordChangedSuccess, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaiseLoginFailedEvent(int userId)
+ public void RaiseLoginFailedEvent(int userId)
{
OnLoginFailed(new IdentityAuditEventArgs(AuditEvent.LoginFailed, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaiseInvalidLoginAttemptEvent(string username)
+ public void RaiseInvalidLoginAttemptEvent(string username)
{
OnLoginFailed(new IdentityAuditEventArgs(AuditEvent.LoginFailed, IpResolver.GetCurrentRequestIpAddress(), username, string.Format("Attempted login for username '{0}' failed", username)));
}
- internal void RaiseLoginRequiresVerificationEvent(int userId)
+ public void RaiseLoginRequiresVerificationEvent(int userId)
{
OnLoginRequiresVerification(new IdentityAuditEventArgs(AuditEvent.LoginRequiresVerification, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaiseLoginSuccessEvent(int userId)
+ public void RaiseLoginSuccessEvent(int userId)
{
OnLoginSuccess(new IdentityAuditEventArgs(AuditEvent.LoginSucces, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaiseLogoutSuccessEvent(int userId)
+ public void RaiseLogoutSuccessEvent(int userId)
{
OnLogoutSuccess(new IdentityAuditEventArgs(AuditEvent.LogoutSuccess, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaisePasswordChangedEvent(int userId)
+ public void RaisePasswordChangedEvent(int userId)
{
OnPasswordChanged(new IdentityAuditEventArgs(AuditEvent.PasswordChanged, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
- internal void RaiseResetAccessFailedCountEvent(int userId)
+ public void RaiseResetAccessFailedCountEvent(int userId)
{
OnResetAccessFailedCount(new IdentityAuditEventArgs(AuditEvent.ResetAccessFailedCount, IpResolver.GetCurrentRequestIpAddress(), affectedUser: userId));
}
diff --git a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserPasswordCheckerResult.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserPasswordCheckerResult.cs
new file mode 100644
index 0000000000..7936fab682
--- /dev/null
+++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserPasswordCheckerResult.cs
@@ -0,0 +1,12 @@
+namespace Umbraco.Core.BackOffice
+{
+ ///
+ /// The result returned from the IBackOfficeUserPasswordChecker
+ ///
+ public enum BackOfficeUserPasswordCheckerResult
+ {
+ ValidCredentials,
+ InvalidCredentials,
+ FallbackToDefaultChecker
+ }
+}
diff --git a/src/Umbraco.Web/Security/BackOfficeUserStore.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs
similarity index 99%
rename from src/Umbraco.Web/Security/BackOfficeUserStore.cs
rename to src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs
index 6f401163aa..b75735e688 100644
--- a/src/Umbraco.Web/Security/BackOfficeUserStore.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs
@@ -5,17 +5,14 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
-using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Identity;
using Umbraco.Core.Models.Membership;
-using Umbraco.Core.Security;
using Umbraco.Core.Services;
-using Umbraco.Web.Models.Identity;
-namespace Umbraco.Web.Security
+namespace Umbraco.Core.BackOffice
{
public class BackOfficeUserStore : DisposableObjectSlim,
IUserPasswordStore,
diff --git a/src/Umbraco.Web/Security/BackOfficeUserValidator.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserValidator.cs
similarity index 90%
rename from src/Umbraco.Web/Security/BackOfficeUserValidator.cs
rename to src/Umbraco.Infrastructure/BackOffice/BackOfficeUserValidator.cs
index 94e9c2e0bd..131bd08ac9 100644
--- a/src/Umbraco.Web/Security/BackOfficeUserValidator.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserValidator.cs
@@ -1,8 +1,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
-using Umbraco.Web.Models.Identity;
-namespace Umbraco.Web.Security
+namespace Umbraco.Core.BackOffice
{
public class BackOfficeUserValidator : UserValidator
where T : BackOfficeIdentityUser
diff --git a/src/Umbraco.Infrastructure/BackOffice/Extensions/ClaimsPrincipalExtensions.cs b/src/Umbraco.Infrastructure/BackOffice/Extensions/ClaimsPrincipalExtensions.cs
new file mode 100644
index 0000000000..a7eea63983
--- /dev/null
+++ b/src/Umbraco.Infrastructure/BackOffice/Extensions/ClaimsPrincipalExtensions.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Linq;
+using System.Security.Claims;
+using System.Security.Principal;
+using Umbraco.Core;
+using Umbraco.Core.BackOffice;
+
+namespace Umbraco.Extensions
+{
+ public static class ClaimsPrincipalExtensions
+ {
+ ///
+ /// This will return the current back office identity if the IPrincipal is the correct type
+ ///
+ ///
+ ///
+ public static UmbracoBackOfficeIdentity GetUmbracoIdentity(this IPrincipal user)
+ {
+ //If it's already a UmbracoBackOfficeIdentity
+ if (user.Identity is UmbracoBackOfficeIdentity backOfficeIdentity) return backOfficeIdentity;
+
+ //Check if there's more than one identity assigned and see if it's a UmbracoBackOfficeIdentity and use that
+ if (user is ClaimsPrincipal claimsPrincipal)
+ {
+ backOfficeIdentity = claimsPrincipal.Identities.OfType().FirstOrDefault();
+ if (backOfficeIdentity != null) return backOfficeIdentity;
+ }
+
+ //Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd and has the back office session
+ if (user.Identity is ClaimsIdentity claimsIdentity && claimsIdentity.IsAuthenticated && claimsIdentity.HasClaim(x => x.Type == Constants.Security.SessionIdClaimType))
+ {
+ try
+ {
+ return UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity);
+ }
+ catch (InvalidOperationException)
+ {
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Umbraco.Infrastructure/BackOffice/Extensions/IdentityExtensions.cs b/src/Umbraco.Infrastructure/BackOffice/Extensions/IdentityExtensions.cs
new file mode 100644
index 0000000000..95a63c6001
--- /dev/null
+++ b/src/Umbraco.Infrastructure/BackOffice/Extensions/IdentityExtensions.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.AspNetCore.Identity;
+
+namespace Umbraco.Extensions
+{
+ public static class IdentityExtensions
+ {
+ public static string ToErrorMessage(this IEnumerable errors)
+ {
+ if (errors == null) throw new ArgumentNullException(nameof(errors));
+ return string.Join(", ", errors.Select(x => x.Description).ToList());
+ }
+ }
+}
diff --git a/src/Umbraco.Infrastructure/BackOffice/IBackOfficeUserPasswordChecker.cs b/src/Umbraco.Infrastructure/BackOffice/IBackOfficeUserPasswordChecker.cs
new file mode 100644
index 0000000000..5874337f4a
--- /dev/null
+++ b/src/Umbraco.Infrastructure/BackOffice/IBackOfficeUserPasswordChecker.cs
@@ -0,0 +1,24 @@
+using System.Threading.Tasks;
+
+namespace Umbraco.Core.BackOffice
+{
+ ///
+ /// Used by the BackOfficeUserManager to check the username/password which allows for developers to more easily
+ /// set the logic for this procedure.
+ ///
+ public interface IBackOfficeUserPasswordChecker
+ {
+ ///
+ /// Checks a password for a user
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// This will allow a developer to auto-link a local account which is required if the user queried doesn't exist locally.
+ /// The user parameter will always contain the username, if the user doesn't exist locally, the other properties will not be filled in.
+ /// A developer can then create a local account by filling in the properties and using UserManager.CreateAsync
+ ///
+ Task CheckPasswordAsync(BackOfficeIdentityUser user, string password);
+ }
+}
diff --git a/src/Umbraco.Web/Security/IUserSessionStore.cs b/src/Umbraco.Infrastructure/BackOffice/IUserSessionStore.cs
similarity index 92%
rename from src/Umbraco.Web/Security/IUserSessionStore.cs
rename to src/Umbraco.Infrastructure/BackOffice/IUserSessionStore.cs
index 06b7c2f165..69d5408cf7 100644
--- a/src/Umbraco.Web/Security/IUserSessionStore.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/IUserSessionStore.cs
@@ -1,7 +1,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
-namespace Umbraco.Core.Security
+namespace Umbraco.Core.BackOffice
{
///
/// An IUserStore interface part to implement if the store supports validating user session Ids
diff --git a/src/Umbraco.Infrastructure/BackOffice/IdentityAuditEventArgs.cs b/src/Umbraco.Infrastructure/BackOffice/IdentityAuditEventArgs.cs
new file mode 100644
index 0000000000..1991f248f1
--- /dev/null
+++ b/src/Umbraco.Infrastructure/BackOffice/IdentityAuditEventArgs.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Threading;
+using Umbraco.Extensions;
+
+
+namespace Umbraco.Core.BackOffice
+{
+ ///
+ /// This class is used by events raised from the BackofficeUserManager
+ ///
+ public class IdentityAuditEventArgs : EventArgs
+ {
+ ///
+ /// The action that got triggered from the audit event
+ ///
+ public AuditEvent Action { get; private set; }
+
+ ///
+ /// Current date/time in UTC format
+ ///
+ public DateTime DateTimeUtc { get; private set; }
+
+ ///
+ /// The source IP address of the user performing the action
+ ///
+ public string IpAddress { get; private set; }
+
+ ///
+ /// The user affected by the event raised
+ ///
+ public int AffectedUser { get; private set; }
+
+ ///
+ /// If a user is performing an action on a different user, then this will be set. Otherwise it will be -1
+ ///
+ public int PerformingUser { get; private set; }
+
+ ///
+ /// An optional comment about the action being logged
+ ///
+ public string Comment { get; private set; }
+
+ ///
+ /// This property is always empty except in the LoginFailed event for an unknown user trying to login
+ ///
+ public string Username { get; private set; }
+
+
+ ///
+ /// Default constructor
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string comment = null, int performingUser = -1, int affectedUser = -1)
+ {
+ DateTimeUtc = DateTime.UtcNow;
+ Action = action;
+
+ IpAddress = ipAddress;
+ Comment = comment;
+ AffectedUser = affectedUser;
+
+ PerformingUser = performingUser == -1
+ ? GetCurrentRequestBackofficeUserId()
+ : performingUser;
+ }
+
+ ///
+ /// Creates an instance without a performing or affected user (the id will be set to -1)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string username, string comment)
+ {
+ DateTimeUtc = DateTime.UtcNow;
+ Action = action;
+
+ IpAddress = ipAddress;
+ Username = username;
+ Comment = comment;
+
+ PerformingUser = -1;
+ }
+
+ public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string username, string comment, int performingUser)
+ {
+ DateTimeUtc = DateTime.UtcNow;
+ Action = action;
+
+ IpAddress = ipAddress;
+ Username = username;
+ Comment = comment;
+
+ PerformingUser = performingUser == -1
+ ? GetCurrentRequestBackofficeUserId()
+ : performingUser;
+ }
+
+ ///
+ /// Returns the current logged in backoffice user's Id logging if there is one
+ ///
+ ///
+ protected int GetCurrentRequestBackofficeUserId()
+ {
+ var userId = -1;
+ /*var backOfficeIdentity = Thread.CurrentPrincipal.GetUmbracoIdentity();
+ if (backOfficeIdentity != null)
+ int.TryParse(backOfficeIdentity.Id.ToString(), out userId);*/
+ return userId;
+ }
+ }
+
+ public enum AuditEvent
+ {
+ AccountLocked,
+ AccountUnlocked,
+ ForgotPasswordRequested,
+ ForgotPasswordChangedSuccess,
+ LoginFailed,
+ LoginRequiresVerification,
+ LoginSucces,
+ LogoutSuccess,
+ PasswordChanged,
+ PasswordReset,
+ ResetAccessFailedCount
+ }
+}
diff --git a/src/Umbraco.Web/Models/Identity/IdentityMapDefinition.cs b/src/Umbraco.Infrastructure/BackOffice/IdentityMapDefinition.cs
similarity index 98%
rename from src/Umbraco.Web/Models/Identity/IdentityMapDefinition.cs
rename to src/Umbraco.Infrastructure/BackOffice/IdentityMapDefinition.cs
index 7c20c6108a..59590907f6 100644
--- a/src/Umbraco.Web/Models/Identity/IdentityMapDefinition.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/IdentityMapDefinition.cs
@@ -1,12 +1,11 @@
using System;
-using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
-namespace Umbraco.Web.Models.Identity
+namespace Umbraco.Core.BackOffice
{
public class IdentityMapDefinition : IMapDefinition
{
diff --git a/src/Umbraco.Web/Security/NopLookupNormalizer.cs b/src/Umbraco.Infrastructure/BackOffice/NopLookupNormalizer.cs
similarity index 91%
rename from src/Umbraco.Web/Security/NopLookupNormalizer.cs
rename to src/Umbraco.Infrastructure/BackOffice/NopLookupNormalizer.cs
index 08aa8d548a..6797d62e6c 100644
--- a/src/Umbraco.Web/Security/NopLookupNormalizer.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/NopLookupNormalizer.cs
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Identity;
-namespace Umbraco.Web.Security
+namespace Umbraco.Core.BackOffice
{
///
/// No-op lookup normalizer to maintain compatibility with ASP.NET Identity 2
diff --git a/src/Umbraco.Web/Security/UmbracoBackOfficeIdentity.cs b/src/Umbraco.Infrastructure/BackOffice/UmbracoBackOfficeIdentity.cs
similarity index 99%
rename from src/Umbraco.Web/Security/UmbracoBackOfficeIdentity.cs
rename to src/Umbraco.Infrastructure/BackOffice/UmbracoBackOfficeIdentity.cs
index c3697d5e9e..c1ec692339 100644
--- a/src/Umbraco.Web/Security/UmbracoBackOfficeIdentity.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/UmbracoBackOfficeIdentity.cs
@@ -2,9 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
-using Umbraco.Web;
-namespace Umbraco.Core.Security
+namespace Umbraco.Core.BackOffice
{
///
diff --git a/src/Umbraco.Web/Models/Identity/UserLoginInfoWrapper.cs b/src/Umbraco.Infrastructure/BackOffice/UserLoginInfoWrapper.cs
similarity index 86%
rename from src/Umbraco.Web/Models/Identity/UserLoginInfoWrapper.cs
rename to src/Umbraco.Infrastructure/BackOffice/UserLoginInfoWrapper.cs
index 336b4c9e72..a441d0299a 100644
--- a/src/Umbraco.Web/Models/Identity/UserLoginInfoWrapper.cs
+++ b/src/Umbraco.Infrastructure/BackOffice/UserLoginInfoWrapper.cs
@@ -1,9 +1,9 @@
using Microsoft.AspNetCore.Identity;
using Umbraco.Core.Models.Identity;
-namespace Umbraco.Web.Models.Identity
+namespace Umbraco.Core.BackOffice
{
- internal class UserLoginInfoWrapper : IUserLoginInfo
+ public class UserLoginInfoWrapper : IUserLoginInfo
{
private readonly UserLoginInfo _info;
diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs
index 3ae92d0179..a240eaf104 100644
--- a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs
+++ b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Specialized;
-using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
@@ -10,8 +9,9 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Services;
using Umbraco.Web.Install.Models;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration.UmbracoSettings;
-using Umbraco.Web.Security;
+using Umbraco.Extensions;
namespace Umbraco.Web.Install.InstallSteps
{
@@ -34,8 +34,9 @@ namespace Umbraco.Web.Install.InstallSteps
private readonly ISecuritySettings _securitySettings;
private readonly IConnectionStrings _connectionStrings;
private readonly ICookieManager _cookieManager;
+ private readonly BackOfficeUserManager _userManager;
- public NewInstallStep(IUserService userService, DatabaseBuilder databaseBuilder, IGlobalSettings globalSettings, IUserPasswordConfiguration passwordConfiguration, ISecuritySettings securitySettings, IConnectionStrings connectionStrings, ICookieManager cookieManager)
+ public NewInstallStep(IUserService userService, DatabaseBuilder databaseBuilder, IGlobalSettings globalSettings, IUserPasswordConfiguration passwordConfiguration, ISecuritySettings securitySettings, IConnectionStrings connectionStrings, ICookieManager cookieManager, BackOfficeUserManager userManager)
{
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
_databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder));
@@ -44,6 +45,7 @@ namespace Umbraco.Web.Install.InstallSteps
_securitySettings = securitySettings ?? throw new ArgumentNullException(nameof(securitySettings));
_connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings));
_cookieManager = cookieManager;
+ _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
}
public override async Task ExecuteAsync(UserModel user)
@@ -59,26 +61,21 @@ namespace Umbraco.Web.Install.InstallSteps
_userService.Save(admin);
- //TODO: This needs to be reintroduced, when users are compatible with ASP.NET Core Identity.
- // var userManager = _httpContextAccessor.GetRequiredHttpContext().GetOwinContext().GetBackOfficeUserManager();
- // var membershipUser = await userManager.FindByIdAsync(Constants.Security.SuperUserId.ToString());
- // if (membershipUser == null)
- // {
- // throw new InvalidOperationException(
- // $"No user found in membership provider with id of {Constants.Security.SuperUserId}.");
- // }
- //
- // //To change the password here we actually need to reset it since we don't have an old one to use to change
- // var resetToken = await userManager.GeneratePasswordResetTokenAsync(membershipUser);
- // if (string.IsNullOrWhiteSpace(resetToken))
- // throw new InvalidOperationException("Could not reset password: unable to generate internal reset token");
- //
- // var resetResult = await userManager.ChangePasswordWithResetAsync(membershipUser.Id, resetToken, user.Password.Trim());
- // if (!resetResult.Succeeded)
- // throw new InvalidOperationException("Could not reset password: " + string.Join(", ", resetResult.Errors.ToErrorMessage()));
-
+ var membershipUser = await _userManager.FindByIdAsync(Constants.Security.SuperUserId.ToString());
+ if (membershipUser == null)
+ {
+ throw new InvalidOperationException(
+ $"No user found in membership provider with id of {Constants.Security.SuperUserId}.");
+ }
+ //To change the password here we actually need to reset it since we don't have an old one to use to change
+ var resetToken = await _userManager.GeneratePasswordResetTokenAsync(membershipUser);
+ if (string.IsNullOrWhiteSpace(resetToken))
+ throw new InvalidOperationException("Could not reset password: unable to generate internal reset token");
+ var resetResult = await _userManager.ChangePasswordWithResetAsync(membershipUser.Id, resetToken, user.Password.Trim());
+ if (!resetResult.Succeeded)
+ throw new InvalidOperationException("Could not reset password: " + string.Join(", ", resetResult.Errors.ToErrorMessage()));
if (user.SubscribeToNewsLetter)
{
diff --git a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj
index 7948c3ea31..1af8ce9119 100644
--- a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj
+++ b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj
@@ -1,4 +1,4 @@
-
+
netstandard2.0
@@ -17,6 +17,7 @@
+
diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs
index a38e002810..8f9ec4d833 100644
--- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs
+++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs
@@ -109,6 +109,8 @@ namespace Umbraco.Tests.Integration.Testing
// Add it!
services.AddUmbracoConfiguration(hostContext.Configuration);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, NoAppCache.Instance, testHelper.GetLoggingConfiguration(), out _);
+
+ CustomTestSetup(services);
});
var host = await hostBuilder.StartAsync();
@@ -123,6 +125,8 @@ namespace Umbraco.Tests.Integration.Testing
#region Common services
+ protected virtual Action CustomTestSetup => services => { };
+
///
/// Returns the DI container
///
diff --git a/src/Umbraco.Tests/Security/NopLookupNormalizerTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/NopLookupNormalizerTests.cs
similarity index 97%
rename from src/Umbraco.Tests/Security/NopLookupNormalizerTests.cs
rename to src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/NopLookupNormalizerTests.cs
index 2abecbb4dd..1c4e08a4de 100644
--- a/src/Umbraco.Tests/Security/NopLookupNormalizerTests.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/NopLookupNormalizerTests.cs
@@ -1,6 +1,6 @@
using System;
using NUnit.Framework;
-using Umbraco.Web.Security;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Tests.Security
{
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UmbracoBackOfficeServiceCollectionExtensionsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UmbracoBackOfficeServiceCollectionExtensionsTests.cs
new file mode 100644
index 0000000000..51fce283f8
--- /dev/null
+++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UmbracoBackOfficeServiceCollectionExtensionsTests.cs
@@ -0,0 +1,42 @@
+using System;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.Extensions.DependencyInjection;
+using NUnit.Framework;
+using Umbraco.Extensions;
+using Umbraco.Core.BackOffice;
+using Umbraco.Tests.Integration.Testing;
+
+namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Extensions
+{
+ [TestFixture]
+ public class UmbracoBackOfficeServiceCollectionExtensionsTests : UmbracoIntegrationTest
+ {
+ [Test]
+ public void AddUmbracoBackOfficeIdentity_ExpectBackOfficeUserStoreResolvable()
+ {
+ var userStore = Services.GetService>();
+
+ Assert.IsNotNull(userStore);
+ Assert.AreEqual(typeof(BackOfficeUserStore), userStore.GetType());
+ }
+
+ [Test]
+ public void AddUmbracoBackOfficeIdentity_ExpectBackOfficeClaimsPrincipalFactoryResolvable()
+ {
+ var principalFactory = Services.GetService>();
+
+ Assert.IsNotNull(principalFactory);
+ Assert.AreEqual(typeof(BackOfficeClaimsPrincipalFactory), principalFactory.GetType());
+ }
+
+ [Test]
+ public void AddUmbracoBackOfficeIdentity_ExpectBackOfficeUserManagerResolvable()
+ {
+ var userManager = Services.GetService();
+
+ Assert.NotNull(userManager);
+ }
+
+ protected override Action CustomTestSetup => (services) => services.AddUmbracoBackOfficeIdentity();
+ }
+}
diff --git a/src/Umbraco.Tests/Security/BackOfficeClaimsPrincipalFactoryTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/BackOfficeClaimsPrincipalFactoryTests.cs
similarity index 95%
rename from src/Umbraco.Tests/Security/BackOfficeClaimsPrincipalFactoryTests.cs
rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/BackOfficeClaimsPrincipalFactoryTests.cs
index b7b516318c..3c01f89554 100644
--- a/src/Umbraco.Tests/Security/BackOfficeClaimsPrincipalFactoryTests.cs
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/BackOfficeClaimsPrincipalFactoryTests.cs
@@ -7,13 +7,12 @@ using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Membership;
-using Umbraco.Core.Security;
-using Umbraco.Web.Models.Identity;
-using Umbraco.Web.Security;
+using Umbraco.Extensions;
-namespace Umbraco.Tests.Security
+namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
{
[TestFixture]
public class BackOfficeClaimsPrincipalFactoryTests
@@ -131,7 +130,7 @@ namespace Umbraco.Tests.Security
const string expectedClaimType = ClaimTypes.Role;
const string expectedClaimValue = "b87309fb-4caf-48dc-b45a-2b752d051508";
- _testUser.Roles.Add(new Core.Models.Identity.IdentityUserRole{RoleId = expectedClaimValue});
+ _testUser.Roles.Add(new global::Umbraco.Core.Models.Identity.IdentityUserRole{RoleId = expectedClaimValue});
_mockUserManager.Setup(x => x.SupportsUserRole).Returns(true);
_mockUserManager.Setup(x => x.GetRolesAsync(_testUser)).ReturnsAsync(new[] {expectedClaimValue});
@@ -148,7 +147,7 @@ namespace Umbraco.Tests.Security
const string expectedClaimType = "custom";
const string expectedClaimValue = "val";
- _testUser.Claims.Add(new Core.Models.Identity.IdentityUserClaim {ClaimType = expectedClaimType, ClaimValue = expectedClaimValue});
+ _testUser.Claims.Add(new global::Umbraco.Core.Models.Identity.IdentityUserClaim {ClaimType = expectedClaimType, ClaimValue = expectedClaimValue});
_mockUserManager.Setup(x => x.SupportsUserClaim).Returns(true);
_mockUserManager.Setup(x => x.GetClaimsAsync(_testUser)).ReturnsAsync(
new List {new Claim(expectedClaimType, expectedClaimValue)});
diff --git a/src/Umbraco.Tests/Security/AuthenticationExtensionsTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/IdentityExtensionsTests.cs
similarity index 94%
rename from src/Umbraco.Tests/Security/AuthenticationExtensionsTests.cs
rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/IdentityExtensionsTests.cs
index e622458c39..baf4a6f062 100644
--- a/src/Umbraco.Tests/Security/AuthenticationExtensionsTests.cs
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/IdentityExtensionsTests.cs
@@ -2,11 +2,11 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Identity;
using NUnit.Framework;
-using Umbraco.Web.Security;
+using Umbraco.Extensions;
namespace Umbraco.Tests.Security
{
- public class AuthenticationExtensionsTests
+ public class IdentityExtensionsTests
{
[Test]
public void ToErrorMessage_When_Errors_Are_Null_Expect_ArgumentNullException()
diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/NopLookupNormalizerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/NopLookupNormalizerTests.cs
new file mode 100644
index 0000000000..e492b060b5
--- /dev/null
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/NopLookupNormalizerTests.cs
@@ -0,0 +1,56 @@
+using System;
+using NUnit.Framework;
+using Umbraco.Core.BackOffice;
+
+namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
+{
+ public class NopLookupNormalizerTests
+ {
+ [Test]
+ [TestCase(null)]
+ [TestCase("")]
+ [TestCase(" ")]
+ public void NormalizeName_When_Name_Null_Or_Whitespace_Expect_Same_Returned(string name)
+ {
+ var sut = new NopLookupNormalizer();
+
+ var normalizedName = sut.NormalizeName(name);
+
+ Assert.AreEqual(name, normalizedName);
+ }
+
+ [Test]
+ public void NormalizeName_Expect_Input_Returned()
+ {
+ var name = Guid.NewGuid().ToString();
+ var sut = new NopLookupNormalizer();
+
+ var normalizedName = sut.NormalizeName(name);
+
+ Assert.AreEqual(name, normalizedName);
+ }
+ [Test]
+ [TestCase(null)]
+ [TestCase("")]
+ [TestCase(" ")]
+ public void NormalizeEmail_When_Name_Null_Or_Whitespace_Expect_Same_Returned(string email)
+ {
+ var sut = new NopLookupNormalizer();
+
+ var normalizedEmail = sut.NormalizeEmail(email);
+
+ Assert.AreEqual(email, normalizedEmail);
+ }
+
+ [Test]
+ public void NormalizeEmail_Expect_Input_Returned()
+ {
+ var email = $"{Guid.NewGuid()}@umbraco";
+ var sut = new NopLookupNormalizer();
+
+ var normalizedEmail = sut.NormalizeEmail(email);
+
+ Assert.AreEqual(email, normalizedEmail);
+ }
+ }
+}
diff --git a/src/Umbraco.Tests/Security/UmbracoBackOfficeIdentityTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentityTests.cs
similarity index 97%
rename from src/Umbraco.Tests/Security/UmbracoBackOfficeIdentityTests.cs
rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentityTests.cs
index 9c16d0c35a..5d0cec0e6e 100644
--- a/src/Umbraco.Tests/Security/UmbracoBackOfficeIdentityTests.cs
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentityTests.cs
@@ -1,16 +1,11 @@
using System;
using System.Linq;
using System.Security.Claims;
-using System.Text;
-using System.Threading.Tasks;
-using System.Web.Security;
-using Newtonsoft.Json;
using NUnit.Framework;
using Umbraco.Core;
-using Umbraco.Core.Security;
-using Umbraco.Core.Services;
+using Umbraco.Core.BackOffice;
-namespace Umbraco.Tests.Security
+namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
{
[TestFixture]
public class UmbracoBackOfficeIdentityTests
diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj
index 56a817f8cb..3176f3d36f 100644
--- a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj
@@ -6,18 +6,6 @@
false
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Umbraco.Tests/Security/BackOfficeUserManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs
similarity index 94%
rename from src/Umbraco.Tests/Security/BackOfficeUserManagerTests.cs
rename to src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs
index 30ed101297..705387b3ae 100644
--- a/src/Umbraco.Tests/Security/BackOfficeUserManagerTests.cs
+++ b/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs
@@ -6,15 +6,15 @@ using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Owin.Security.DataProtection;
using Moq;
using NUnit.Framework;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Membership;
using Umbraco.Net;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Security
{
- public class BackOfficeUserManagerTests
+ public class BackOfficeOwinUserManagerTests
{
[Test]
public async Task CheckPasswordAsync_When_Default_Password_Hasher_Validates_Umbraco7_Hash_Expect_Valid_Password()
@@ -32,7 +32,7 @@ namespace Umbraco.Tests.Security
mockPasswordConfiguration.Setup(x => x.HashAlgorithmType)
.Returns("HMACSHA256");
- var userManager = BackOfficeUserManager.Create(
+ var userManager = BackOfficeOwinUserManager.Create(
mockPasswordConfiguration.Object,
mockIpResolver.Object,
mockUserStore.Object,
diff --git a/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs b/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs
index 5e9b731aa9..7b1ca53104 100644
--- a/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs
+++ b/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs
@@ -6,9 +6,9 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.Owin.Security.DataProtection;
using Moq;
using NUnit.Framework;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Membership;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Security
diff --git a/src/Umbraco.Tests/Security/UmbracoSecurityStampValidatorTests.cs b/src/Umbraco.Tests/Security/UmbracoSecurityStampValidatorTests.cs
index 92fa032271..b80e526037 100644
--- a/src/Umbraco.Tests/Security/UmbracoSecurityStampValidatorTests.cs
+++ b/src/Umbraco.Tests/Security/UmbracoSecurityStampValidatorTests.cs
@@ -11,18 +11,19 @@ using Microsoft.Owin.Security.Cookies;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Membership;
using Umbraco.Net;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Security;
+
namespace Umbraco.Tests.Security
{
public class UmbracoSecurityStampValidatorTests
{
private Mock _mockOwinContext;
- private Mock> _mockUserManager;
+ private Mock _mockUserManager;
private Mock _mockSignInManager;
private AuthenticationTicket _testAuthTicket;
@@ -34,7 +35,7 @@ namespace Umbraco.Tests.Security
public void OnValidateIdentity_When_GetUserIdCallback_Is_Null_Expect_ArgumentNullException()
{
Assert.Throws(() => UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MaxValue, null, null));
}
@@ -42,7 +43,7 @@ namespace Umbraco.Tests.Security
public async Task OnValidateIdentity_When_Validation_Interval_Not_Met_Expect_No_Op()
{
var func = UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MaxValue, null, identity => throw new Exception());
_testAuthTicket.Properties.IssuedUtc = DateTimeOffset.UtcNow;
@@ -61,11 +62,11 @@ namespace Umbraco.Tests.Security
public void OnValidateIdentity_When_Time_To_Validate_But_No_UserManager_Expect_InvalidOperationException()
{
var func = UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MinValue, null, identity => throw new Exception());
- _mockOwinContext.Setup(x => x.Get>(It.IsAny()))
- .Returns((BackOfficeUserManager) null);
+ _mockOwinContext.Setup(x => x.Get(It.IsAny()))
+ .Returns((BackOfficeOwinUserManager) null);
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
@@ -79,7 +80,7 @@ namespace Umbraco.Tests.Security
public void OnValidateIdentity_When_Time_To_Validate_But_No_SignInManager_Expect_InvalidOperationException()
{
var func = UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MinValue, null, identity => throw new Exception());
_mockOwinContext.Setup(x => x.Get(It.IsAny()))
@@ -99,7 +100,7 @@ namespace Umbraco.Tests.Security
var userId = Guid.NewGuid().ToString();
var func = UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MinValue, null, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId))
@@ -122,7 +123,7 @@ namespace Umbraco.Tests.Security
var userId = Guid.NewGuid().ToString();
var func = UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MinValue, null, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId)).ReturnsAsync(_testUser);
@@ -145,7 +146,7 @@ namespace Umbraco.Tests.Security
var userId = Guid.NewGuid().ToString();
var func = UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MinValue, null, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId)).ReturnsAsync(_testUser);
@@ -169,7 +170,7 @@ namespace Umbraco.Tests.Security
var userId = Guid.NewGuid().ToString();
var func = UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MinValue, null, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId)).ReturnsAsync(_testUser);
@@ -193,7 +194,7 @@ namespace Umbraco.Tests.Security
var expectedIdentity = new ClaimsIdentity(new List {new Claim("sub", "bob")});
var regenFuncCalled = false;
- Func, BackOfficeIdentityUser, Task> regenFunc =
+ Func> regenFunc =
(signInManager, userManager, user) =>
{
regenFuncCalled = true;
@@ -201,7 +202,7 @@ namespace Umbraco.Tests.Security
};
var func = UmbracoSecurityStampValidator
- .OnValidateIdentity, BackOfficeIdentityUser>(
+ .OnValidateIdentity(
TimeSpan.MinValue, regenFunc, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId)).ReturnsAsync(_testUser);
@@ -249,7 +250,7 @@ namespace Umbraco.Tests.Security
new AuthenticationProperties());
_testOptions = new CookieAuthenticationOptions { AuthenticationType = _testAuthType };
- _mockUserManager = new Mock>(
+ _mockUserManager = new Mock(
new Mock().Object,
new Mock().Object,
new Mock>().Object,
@@ -266,7 +267,7 @@ namespace Umbraco.Tests.Security
new Mock().Object);
_mockOwinContext = new Mock();
- _mockOwinContext.Setup(x => x.Get>(It.IsAny()))
+ _mockOwinContext.Setup(x => x.Get(It.IsAny()))
.Returns(_mockUserManager.Object);
_mockOwinContext.Setup(x => x.Get(It.IsAny()))
.Returns(_mockSignInManager.Object);
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs
index 5031d178bf..72941633e7 100644
--- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs
@@ -4,7 +4,7 @@ using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Owin;
-using Umbraco.Core.Security;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Tests.TestHelpers.ControllerTesting
{
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs
index 66310caea9..793d31a5d3 100644
--- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs
@@ -8,6 +8,7 @@ using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Security;
using Moq;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Dictionary;
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 77aba483d7..3ca52b73f1 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -146,11 +146,8 @@
-
-
-
-
+
@@ -275,7 +272,6 @@
-
diff --git a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs
index 31d1f25c1d..1158d00b4e 100644
--- a/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs
+++ b/src/Umbraco.Tests/Web/Controllers/UsersControllerTests.cs
@@ -28,7 +28,6 @@ using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Persistence.Querying;
-using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.ControllerTesting;
@@ -46,8 +45,8 @@ using Umbraco.Web.Routing;
using Umbraco.Core.Media;
using Umbraco.Net;
using Umbraco.Persistance.SqlCe;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Security;
+using BackOfficeIdentityUser = Umbraco.Core.BackOffice.BackOfficeIdentityUser;
namespace Umbraco.Tests.Web.Controllers
{
@@ -474,7 +473,7 @@ namespace Umbraco.Tests.Web.Controllers
mockUserManager.Verify();
}
- private UsersController CreateSut(IMock> mockUserManager = null)
+ private UsersController CreateSut(IMock mockUserManager = null)
{
var mockLocalizedTextService = new Mock();
mockLocalizedTextService.Setup(x => x.Localize(It.IsAny(), It.IsAny(), It.IsAny>()))
@@ -515,9 +514,9 @@ namespace Umbraco.Tests.Web.Controllers
return usersController;
}
- private static Mock> CreateMockUserManager()
+ private static Mock CreateMockUserManager()
{
- return new Mock>(
+ return new Mock(
new Mock().Object,
new Mock().Object,
new Mock>().Object,
diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs
new file mode 100644
index 0000000000..f3a9a528ae
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Security.Claims;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Umbraco.Core;
+using Umbraco.Core.BackOffice;
+using Umbraco.Core.Mapping;
+using Umbraco.Net;
+using Umbraco.Web.Common.AspNetCore;
+
+namespace Umbraco.Extensions
+{
+ public static class UmbracoBackOfficeServiceCollectionExtensions
+ {
+ public static void AddUmbracoBackOfficeIdentity(this IServiceCollection services)
+ {
+ services.AddDataProtection();
+
+ // UmbracoMapper - hack?
+ services.TryAddSingleton();
+ services.TryAddSingleton(s => new MapDefinitionCollection(new[] {s.GetService()}));
+ services.TryAddSingleton();
+
+ services.TryAddScoped();
+
+ services.AddIdentityCore(options =>
+ {
+ options.User.RequireUniqueEmail = true;
+
+ // TODO: Configure password configuration
+ /*options.Password.RequiredLength = passwordConfiguration.RequiredLength;
+ options.Password.RequireNonAlphanumeric = passwordConfiguration.RequireNonLetterOrDigit;
+ options.Password.RequireDigit = passwordConfiguration.RequireDigit;
+ options.Password.RequireLowercase = passwordConfiguration.RequireLowercase;
+ options.Password.RequireUppercase = passwordConfiguration.RequireUppercase;
+ options.Lockout.MaxFailedAccessAttempts = passwordConfiguration.MaxFailedAccessAttemptsBeforeLockout;*/
+
+ options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier;
+ options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
+ options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role;
+ options.ClaimsIdentity.SecurityStampClaimType = Constants.Web.SecurityStampClaimType;
+
+ options.Lockout.AllowedForNewUsers = true;
+ options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromDays(30);
+ })
+ .AddDefaultTokenProviders()
+ .AddUserStore()
+ .AddUserManager()
+ .AddClaimsPrincipalFactory>();
+
+ services.AddScoped();
+ services.TryAddScoped>();
+
+ }
+ }
+}
diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs
index 95eaab851b..547a320de1 100644
--- a/src/Umbraco.Web.UI.NetCore/Startup.cs
+++ b/src/Umbraco.Web.UI.NetCore/Startup.cs
@@ -43,6 +43,7 @@ namespace Umbraco.Web.UI.BackOffice
services.AddUmbracoCore(_env, out var factory);
services.AddUmbracoWebComponents();
services.AddUmbracoRuntimeMinifier(_config);
+ services.AddUmbracoBackOfficeIdentity();
services.AddMvc();
diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs
index bd2520aa90..51c47233c7 100644
--- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs
+++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs
@@ -8,10 +8,9 @@ using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Net;
-using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
-using Umbraco.Web.Security;
+using Umbraco.Extensions;
namespace Umbraco.Core.Compose
{
diff --git a/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs b/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs
index 84fb0e6bb8..dcb5fac32d 100644
--- a/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs
+++ b/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs
@@ -26,14 +26,14 @@ namespace Umbraco.Web.Compose
{
//BackOfficeUserManager.AccountLocked += ;
//BackOfficeUserManager.AccountUnlocked += ;
- BackOfficeUserManager.ForgotPasswordRequested += OnForgotPasswordRequest;
- BackOfficeUserManager.ForgotPasswordChangedSuccess += OnForgotPasswordChange;
- BackOfficeUserManager.LoginFailed += OnLoginFailed;
+ BackOfficeOwinUserManager.ForgotPasswordRequested += OnForgotPasswordRequest;
+ BackOfficeOwinUserManager.ForgotPasswordChangedSuccess += OnForgotPasswordChange;
+ BackOfficeOwinUserManager.LoginFailed += OnLoginFailed;
//BackOfficeUserManager.LoginRequiresVerification += ;
- BackOfficeUserManager.LoginSuccess += OnLoginSuccess;
- BackOfficeUserManager.LogoutSuccess += OnLogoutSuccess;
- BackOfficeUserManager.PasswordChanged += OnPasswordChanged;
- BackOfficeUserManager.PasswordReset += OnPasswordReset;
+ BackOfficeOwinUserManager.LoginSuccess += OnLoginSuccess;
+ BackOfficeOwinUserManager.LogoutSuccess += OnLogoutSuccess;
+ BackOfficeOwinUserManager.PasswordChanged += OnPasswordChanged;
+ BackOfficeOwinUserManager.PasswordReset += OnPasswordReset;
//BackOfficeUserManager.ResetAccessFailedCount += ;
}
diff --git a/src/Umbraco.Web/Composing/CompositionExtensions/WebMappingProfiles.cs b/src/Umbraco.Web/Composing/CompositionExtensions/WebMappingProfiles.cs
index 21a242ee17..44d86df59c 100644
--- a/src/Umbraco.Web/Composing/CompositionExtensions/WebMappingProfiles.cs
+++ b/src/Umbraco.Web/Composing/CompositionExtensions/WebMappingProfiles.cs
@@ -1,7 +1,7 @@
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Composing;
using Umbraco.Core.Mapping;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Models.Mapping;
namespace Umbraco.Web.Composing.CompositionExtensions
diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs
index 063bc89269..81d714926f 100644
--- a/src/Umbraco.Web/Editors/AuthenticationController.cs
+++ b/src/Umbraco.Web/Editors/AuthenticationController.cs
@@ -25,10 +25,9 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using IUser = Umbraco.Core.Models.Membership.IUser;
using Umbraco.Core.Mapping;
-using Umbraco.Web.Models.Identity;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
-using Umbraco.Core.IO;
+using Umbraco.Extensions;
using Umbraco.Web.Routing;
namespace Umbraco.Web.Editors
@@ -42,7 +41,7 @@ namespace Umbraco.Web.Editors
[IsBackOffice]
public class AuthenticationController : UmbracoApiController
{
- private BackOfficeUserManager _userManager;
+ private BackOfficeOwinUserManager _userManager;
private BackOfficeSignInManager _signInManager;
private readonly IUserPasswordConfiguration _passwordConfiguration;
private readonly IHostingEnvironment _hostingEnvironment;
@@ -76,8 +75,8 @@ namespace Umbraco.Web.Editors
_emailSender = emailSender;
}
- protected BackOfficeUserManager UserManager => _userManager
- ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager());
+ protected BackOfficeOwinUserManager UserManager => _userManager
+ ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager());
protected BackOfficeSignInManager SignInManager => _signInManager
?? (_signInManager = TryGetOwinContext().Result.GetBackOfficeSignInManager());
diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs
index 5b3a01052d..4e65d0200d 100644
--- a/src/Umbraco.Web/Editors/BackOfficeController.cs
+++ b/src/Umbraco.Web/Editors/BackOfficeController.cs
@@ -18,15 +18,16 @@ using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using Umbraco.Core.Services;
using Umbraco.Web.Features;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Security;
using Constants = Umbraco.Core.Constants;
using Umbraco.Core.Configuration.Grid;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Core.WebAssets;
+using Umbraco.Extensions;
using Umbraco.Web.Trees;
using Umbraco.Web.WebAssets;
+using BackOfficeIdentityUser = Umbraco.Core.BackOffice.BackOfficeIdentityUser;
namespace Umbraco.Web.Editors
{
@@ -40,7 +41,7 @@ namespace Umbraco.Web.Editors
{
private readonly UmbracoFeatures _features;
private readonly IRuntimeState _runtimeState;
- private BackOfficeUserManager _userManager;
+ private BackOfficeOwinUserManager _userManager;
private BackOfficeSignInManager _signInManager;
private readonly IUmbracoVersion _umbracoVersion;
private readonly IGridConfig _gridConfig;
@@ -85,7 +86,7 @@ namespace Umbraco.Web.Editors
protected BackOfficeSignInManager SignInManager => _signInManager ?? (_signInManager = OwinContext.GetBackOfficeSignInManager());
- protected BackOfficeUserManager UserManager => _userManager ?? (_userManager = OwinContext.GetBackOfficeUserManager());
+ protected BackOfficeOwinUserManager UserManager => _userManager ?? (_userManager = OwinContext.GetBackOfficeUserManager());
protected IAuthenticationManager AuthenticationManager => OwinContext.Authentication;
diff --git a/src/Umbraco.Web/Editors/CurrentUserController.cs b/src/Umbraco.Web/Editors/CurrentUserController.cs
index 2ad09dc895..2bfbcb0c22 100644
--- a/src/Umbraco.Web/Editors/CurrentUserController.cs
+++ b/src/Umbraco.Web/Editors/CurrentUserController.cs
@@ -25,6 +25,7 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Web.Routing;
using Umbraco.Core.Media;
+using Umbraco.Extensions;
namespace Umbraco.Web.Editors
{
diff --git a/src/Umbraco.Web/Editors/PasswordChanger.cs b/src/Umbraco.Web/Editors/PasswordChanger.cs
index b6757f76cc..4b3995ef06 100644
--- a/src/Umbraco.Web/Editors/PasswordChanger.cs
+++ b/src/Umbraco.Web/Editors/PasswordChanger.cs
@@ -4,10 +4,8 @@ using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
-using Umbraco.Core.Models.Identity;
-using Umbraco.Core.Security;
+using Umbraco.Extensions;
using Umbraco.Web.Models;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Security;
using IUser = Umbraco.Core.Models.Membership.IUser;
@@ -34,7 +32,7 @@ namespace Umbraco.Web.Editors
IUser currentUser,
IUser savingUser,
ChangingPasswordModel passwordModel,
- BackOfficeUserManager userMgr)
+ BackOfficeOwinUserManager userMgr)
{
if (passwordModel == null) throw new ArgumentNullException(nameof(passwordModel));
if (userMgr == null) throw new ArgumentNullException(nameof(userMgr));
diff --git a/src/Umbraco.Web/Editors/UsersController.cs b/src/Umbraco.Web/Editors/UsersController.cs
index 9a35990be7..073929b7a7 100644
--- a/src/Umbraco.Web/Editors/UsersController.cs
+++ b/src/Umbraco.Web/Editors/UsersController.cs
@@ -12,6 +12,7 @@ using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
@@ -25,7 +26,6 @@ using Umbraco.Core.Strings;
using Umbraco.Web.Editors.Filters;
using Umbraco.Web.Models;
using Umbraco.Web.Models.ContentEditing;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Filters;
@@ -37,7 +37,7 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Web.Routing;
using Umbraco.Core.Media;
-using Umbraco.Web.Security;
+using Umbraco.Extensions;
namespace Umbraco.Web.Editors
{
diff --git a/src/Umbraco.Web/OwinExtensions.cs b/src/Umbraco.Web/OwinExtensions.cs
index 52c1187707..4ea4040ec6 100644
--- a/src/Umbraco.Web/OwinExtensions.cs
+++ b/src/Umbraco.Web/OwinExtensions.cs
@@ -3,7 +3,6 @@ using System.Web;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Umbraco.Core;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Security;
namespace Umbraco.Web
@@ -72,13 +71,13 @@ namespace Umbraco.Web
/// This is required because to extract the user manager we need to user a custom service since owin only deals in generics and
/// developers could register their own user manager types
///
- public static BackOfficeUserManager GetBackOfficeUserManager(this IOwinContext owinContext)
+ public static BackOfficeOwinUserManager GetBackOfficeUserManager(this IOwinContext owinContext)
{
- var marker = owinContext.Get(BackOfficeUserManager.OwinMarkerKey)
+ var marker = owinContext.Get(BackOfficeOwinUserManager.OwinMarkerKey)
?? throw new NullReferenceException($"No {typeof (IBackOfficeUserManagerMarker)}, i.e. no Umbraco back-office, has been registered with Owin.");
return marker.GetManager(owinContext)
- ?? throw new NullReferenceException($"Could not resolve an instance of {typeof (BackOfficeUserManager)} from the {typeof (IOwinContext)}.");
+ ?? throw new NullReferenceException($"Could not resolve an instance of {typeof (BackOfficeOwinUserManager)} from the {typeof (IOwinContext)}.");
}
///
diff --git a/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs b/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs
index af7aebce3a..930cabeee3 100644
--- a/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs
+++ b/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs
@@ -1,8 +1,8 @@
using System;
using System.DirectoryServices.AccountManagement;
using System.Threading.Tasks;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
-using Umbraco.Web.Models.Identity;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs
index 3f129f941d..81c5408e98 100644
--- a/src/Umbraco.Web/Security/AppBuilderExtensions.cs
+++ b/src/Umbraco.Web/Security/AppBuilderExtensions.cs
@@ -11,6 +11,7 @@ using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Owin;
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
@@ -19,7 +20,6 @@ using Umbraco.Core.Mapping;
using Umbraco.Net;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
-using Umbraco.Web.Models.Identity;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Security
@@ -43,8 +43,8 @@ namespace Umbraco.Web.Security
if (services == null) throw new ArgumentNullException(nameof(services));
//Configure Umbraco user manager to be created per request
- app.CreatePerOwinContext(
- (options, owinContext) => BackOfficeUserManager.Create(
+ app.CreatePerOwinContext(
+ (options, owinContext) => BackOfficeOwinUserManager.Create(
services.UserService,
services.EntityService,
services.ExternalLoginService,
@@ -56,7 +56,7 @@ namespace Umbraco.Web.Security
app.GetDataProtectionProvider(),
new NullLogger>()));
- app.SetBackOfficeUserManagerType();
+ app.SetBackOfficeUserManagerType();
//Create a sign in manager per request
app.CreatePerOwinContext((options, context) => BackOfficeSignInManager.Create(context, globalSettings, app.CreateLogger()));
@@ -77,8 +77,8 @@ namespace Umbraco.Web.Security
if (customUserStore == null) throw new ArgumentNullException(nameof(customUserStore));
//Configure Umbraco user manager to be created per request
- app.CreatePerOwinContext(
- (options, owinContext) => BackOfficeUserManager.Create(
+ app.CreatePerOwinContext(
+ (options, owinContext) => BackOfficeOwinUserManager.Create(
passwordConfiguration,
ipResolver,
customUserStore,
@@ -86,7 +86,7 @@ namespace Umbraco.Web.Security
app.GetDataProtectionProvider(),
new NullLogger>()));
- app.SetBackOfficeUserManagerType();
+ app.SetBackOfficeUserManagerType();
//Create a sign in manager per request
app.CreatePerOwinContext((options, context) => BackOfficeSignInManager.Create(context, globalSettings, app.CreateLogger(typeof(BackOfficeSignInManager).FullName)));
@@ -153,7 +153,7 @@ namespace Umbraco.Web.Security
// logs in. This is a security feature which is used when you
// change a password or add an external login to your account.
OnValidateIdentity = UmbracoSecurityStampValidator
- .OnValidateIdentity(
+ .OnValidateIdentity(
TimeSpan.FromMinutes(30),
(signInManager, manager, user) => signInManager.CreateUserIdentityAsync(user),
identity => identity.GetUserId()),
@@ -240,7 +240,7 @@ namespace Umbraco.Web.Security
// a generic strongly typed instance
app.Use((context, func) =>
{
- context.Set(BackOfficeUserManager.OwinMarkerKey, new BackOfficeUserManagerMarker());
+ context.Set(BackOfficeOwinUserManager.OwinMarkerKey, new BackOfficeUserManagerMarker());
return func();
});
}
diff --git a/src/Umbraco.Web/Security/AuthenticationExtensions.cs b/src/Umbraco.Web/Security/AuthenticationExtensions.cs
index 7d76eaa7be..deb735ca56 100644
--- a/src/Umbraco.Web/Security/AuthenticationExtensions.cs
+++ b/src/Umbraco.Web/Security/AuthenticationExtensions.cs
@@ -12,8 +12,9 @@ using Microsoft.Owin;
using Microsoft.Owin.Security;
using Newtonsoft.Json;
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
+using Umbraco.Extensions;
using Umbraco.Web.Composing;
-using Umbraco.Core.Security;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Security
@@ -333,38 +334,6 @@ namespace Umbraco.Web.Security
return secureDataFormat.Unprotect(formsCookie);
}
- ///
- /// This will return the current back office identity if the IPrincipal is the correct type
- ///
- ///
- ///
- public static UmbracoBackOfficeIdentity GetUmbracoIdentity(this IPrincipal user)
- {
- //If it's already a UmbracoBackOfficeIdentity
- if (user.Identity is UmbracoBackOfficeIdentity backOfficeIdentity) return backOfficeIdentity;
-
- //Check if there's more than one identity assigned and see if it's a UmbracoBackOfficeIdentity and use that
- if (user is ClaimsPrincipal claimsPrincipal)
- {
- backOfficeIdentity = claimsPrincipal.Identities.OfType().FirstOrDefault();
- if (backOfficeIdentity != null) return backOfficeIdentity;
- }
-
- //Otherwise convert to a UmbracoBackOfficeIdentity if it's auth'd and has the back office session
- if (user.Identity is ClaimsIdentity claimsIdentity && claimsIdentity.IsAuthenticated && claimsIdentity.HasClaim(x => x.Type == Constants.Security.SessionIdClaimType))
- {
- try
- {
- return UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity);
- }
- catch (InvalidOperationException)
- {
- }
- }
-
- return null;
- }
-
///
/// Ensures that the thread culture is set based on the back office user's culture
///
@@ -383,12 +352,5 @@ namespace Umbraco.Web.Security
/// Used so that we aren't creating a new CultureInfo object for every single request
///
private static readonly ConcurrentDictionary UserCultures = new ConcurrentDictionary();
-
- public static string ToErrorMessage(this IEnumerable errors)
- {
- if (errors == null) throw new ArgumentNullException(nameof(errors));
- return string.Join(", ", errors.Select(x => x.Description).ToList());
- }
-
}
}
diff --git a/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs b/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs
index 01f8dc4e96..35edb251f9 100644
--- a/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs
+++ b/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs
@@ -4,10 +4,8 @@ using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Umbraco.Core;
-using Umbraco.Web.Composing;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
-using Umbraco.Core.IO;
-using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
@@ -77,12 +75,12 @@ namespace Umbraco.Web.Security
Expires = DateTime.Now.AddYears(-1),
Path = "/"
});
- context.Response.Cookies.Append(Core.Constants.Web.PreviewCookieName, "", new CookieOptions
+ context.Response.Cookies.Append(Constants.Web.PreviewCookieName, "", new CookieOptions
{
Expires = DateTime.Now.AddYears(-1),
Path = "/"
});
- context.Response.Cookies.Append(Core.Constants.Security.BackOfficeExternalCookieName, "", new CookieOptions
+ context.Response.Cookies.Append(Constants.Security.BackOfficeExternalCookieName, "", new CookieOptions
{
Expires = DateTime.Now.AddYears(-1),
Path = "/"
diff --git a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs
new file mode 100644
index 0000000000..005ae972c3
--- /dev/null
+++ b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Security.Claims;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.Owin.Security.DataProtection;
+using Umbraco.Core;
+using Umbraco.Core.BackOffice;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Mapping;
+using Umbraco.Core.Security;
+using Umbraco.Core.Services;
+using Umbraco.Net;
+
+namespace Umbraco.Web.Security
+{
+ public class BackOfficeOwinUserManager : BackOfficeUserManager
+ {
+ public const string OwinMarkerKey = "Umbraco.Web.Security.Identity.BackOfficeUserManagerMarker";
+
+ public BackOfficeOwinUserManager(
+ IPasswordConfiguration passwordConfiguration,
+ IIpResolver ipResolver,
+ IUserStore store,
+ IOptions optionsAccessor,
+ IEnumerable> userValidators,
+ IEnumerable> passwordValidators,
+ ILookupNormalizer keyNormalizer,
+ IdentityErrorDescriber errors,
+ IDataProtectionProvider dataProtectionProvider,
+ ILogger> logger)
+ : base(ipResolver, store, optionsAccessor, null, userValidators, passwordValidators, keyNormalizer, errors, null, logger)
+ {
+ PasswordConfiguration = passwordConfiguration;
+ InitUserManager(this, dataProtectionProvider);
+ }
+
+ #region Static Create methods
+
+ ///
+ /// Creates a BackOfficeUserManager instance with all default options and the default BackOfficeUserManager
+ ///
+ public static BackOfficeOwinUserManager Create(
+ IUserService userService,
+ IEntityService entityService,
+ IExternalLoginService externalLoginService,
+ IGlobalSettings globalSettings,
+ UmbracoMapper mapper,
+ IPasswordConfiguration passwordConfiguration,
+ IIpResolver ipResolver,
+ IdentityErrorDescriber errors,
+ IDataProtectionProvider dataProtectionProvider,
+ ILogger> logger)
+ {
+ var store = new BackOfficeUserStore(userService, entityService, externalLoginService, globalSettings, mapper);
+
+ return Create(
+ passwordConfiguration,
+ ipResolver,
+ store,
+ errors,
+ dataProtectionProvider,
+ logger);
+ }
+
+ ///
+ /// Creates a BackOfficeUserManager instance with all default options and a custom BackOfficeUserManager instance
+ ///
+ public static BackOfficeOwinUserManager Create(
+ IPasswordConfiguration passwordConfiguration,
+ IIpResolver ipResolver,
+ IUserStore customUserStore,
+ IdentityErrorDescriber errors,
+ IDataProtectionProvider dataProtectionProvider,
+ ILogger> logger)
+ {
+ var options = new IdentityOptions();
+
+ // Configure validation logic for usernames
+ var userValidators = new List> { new BackOfficeUserValidator() };
+ options.User.RequireUniqueEmail = true;
+
+ // Configure validation logic for passwords
+ var passwordValidators = new List> { new PasswordValidator() };
+ options.Password.RequiredLength = passwordConfiguration.RequiredLength;
+ options.Password.RequireNonAlphanumeric = passwordConfiguration.RequireNonLetterOrDigit;
+ options.Password.RequireDigit = passwordConfiguration.RequireDigit;
+ options.Password.RequireLowercase = passwordConfiguration.RequireLowercase;
+ options.Password.RequireUppercase = passwordConfiguration.RequireUppercase;
+
+ // Ensure Umbraco security stamp claim type is used
+ options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier;
+ options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
+ options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role;
+ options.ClaimsIdentity.SecurityStampClaimType = Constants.Web.SecurityStampClaimType;
+
+ options.Lockout.AllowedForNewUsers = true;
+ options.Lockout.MaxFailedAccessAttempts = passwordConfiguration.MaxFailedAccessAttemptsBeforeLockout;
+ //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.
+ options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromDays(30);
+
+ return new BackOfficeOwinUserManager(
+ passwordConfiguration,
+ ipResolver,
+ customUserStore,
+ new OptionsWrapper(options),
+ userValidators,
+ passwordValidators,
+ new NopLookupNormalizer(),
+ errors,
+ dataProtectionProvider,
+ logger);
+ }
+
+ #endregion
+
+ protected override IPasswordHasher GetDefaultPasswordHasher(IPasswordConfiguration passwordConfiguration)
+ {
+ return new UserAwarePasswordHasher(new PasswordSecurity(passwordConfiguration));
+ }
+
+ protected void InitUserManager(BackOfficeOwinUserManager manager, IDataProtectionProvider dataProtectionProvider)
+ {
+ // use a custom hasher based on our membership provider
+ PasswordHasher = GetDefaultPasswordHasher(PasswordConfiguration);
+
+ // set OWIN data protection token provider as default
+ if (dataProtectionProvider != null)
+ {
+ manager.RegisterTokenProvider(
+ TokenOptions.DefaultProvider,
+ new OwinDataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity"))
+ {
+ TokenLifespan = TimeSpan.FromDays(3)
+ });
+ }
+
+ // register ASP.NET Core Identity token providers
+ manager.RegisterTokenProvider(TokenOptions.DefaultEmailProvider, new EmailTokenProvider());
+ manager.RegisterTokenProvider(TokenOptions.DefaultPhoneProvider, new PhoneNumberTokenProvider());
+ manager.RegisterTokenProvider(TokenOptions.DefaultAuthenticatorProvider, new AuthenticatorTokenProvider());
+ }
+ }
+}
diff --git a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs
index bbb4328fc3..5e172d2d77 100644
--- a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs
+++ b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs
@@ -8,9 +8,9 @@ using Microsoft.Owin;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
-using Umbraco.Core.Security;
-using Umbraco.Web.Models.Identity;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/BackOfficeUserManagerMarker.cs b/src/Umbraco.Web/Security/BackOfficeUserManagerMarker.cs
index b3eb9da3d5..dd657b48bf 100644
--- a/src/Umbraco.Web/Security/BackOfficeUserManagerMarker.cs
+++ b/src/Umbraco.Web/Security/BackOfficeUserManagerMarker.cs
@@ -1,6 +1,6 @@
using System;
using Microsoft.Owin;
-using Umbraco.Web.Models.Identity;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Web.Security
{
@@ -15,9 +15,9 @@ namespace Umbraco.Web.Security
where TManager : BackOfficeUserManager
where TUser : BackOfficeIdentityUser
{
- public BackOfficeUserManager GetManager(IOwinContext owin)
+ public BackOfficeOwinUserManager GetManager(IOwinContext owin)
{
- var mgr = owin.Get() as BackOfficeUserManager;
+ var mgr = owin.Get() as BackOfficeOwinUserManager;
if (mgr == null) throw new InvalidOperationException("Could not cast the registered back office user of type " + typeof(TManager) + " to " + typeof(BackOfficeUserManager));
return mgr;
}
diff --git a/src/Umbraco.Web/Security/ExternalSignInAutoLinkOptions.cs b/src/Umbraco.Web/Security/ExternalSignInAutoLinkOptions.cs
index abe5aeb196..fc84cd270d 100644
--- a/src/Umbraco.Web/Security/ExternalSignInAutoLinkOptions.cs
+++ b/src/Umbraco.Web/Security/ExternalSignInAutoLinkOptions.cs
@@ -1,7 +1,7 @@
using System;
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
using Umbraco.Web.Composing;
-using Umbraco.Web.Models.Identity;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/FixWindowsAuthMiddlware.cs b/src/Umbraco.Web/Security/FixWindowsAuthMiddlware.cs
index 30038e1f31..9bad4bec17 100644
--- a/src/Umbraco.Web/Security/FixWindowsAuthMiddlware.cs
+++ b/src/Umbraco.Web/Security/FixWindowsAuthMiddlware.cs
@@ -4,7 +4,7 @@ using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.Owin;
using Umbraco.Core;
-using Umbraco.Core.Security;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/IBackOfficeUserManagerMarker.cs b/src/Umbraco.Web/Security/IBackOfficeUserManagerMarker.cs
index bfe2590eb8..16c0666c9c 100644
--- a/src/Umbraco.Web/Security/IBackOfficeUserManagerMarker.cs
+++ b/src/Umbraco.Web/Security/IBackOfficeUserManagerMarker.cs
@@ -1,5 +1,4 @@
using Microsoft.Owin;
-using Umbraco.Web.Models.Identity;
namespace Umbraco.Web.Security
{
@@ -10,6 +9,6 @@ namespace Umbraco.Web.Security
///
internal interface IBackOfficeUserManagerMarker
{
- BackOfficeUserManager GetManager(IOwinContext owin);
+ BackOfficeOwinUserManager GetManager(IOwinContext owin);
}
}
diff --git a/src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs b/src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs
index 9b9e7443be..2fae308eb0 100644
--- a/src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs
+++ b/src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs
@@ -1,6 +1,5 @@
using System.Threading.Tasks;
-using Umbraco.Core.Models.Identity;
-using Umbraco.Web.Models.Identity;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs b/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs
index 5847250b41..d37974276c 100644
--- a/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs
+++ b/src/Umbraco.Web/Security/IdentityAuditEventArgs.cs
@@ -1,5 +1,6 @@
using System;
using System.Threading;
+using Umbraco.Extensions;
namespace Umbraco.Web.Security
diff --git a/src/Umbraco.Web/Security/OwinDataProtectorTokenProvider.cs b/src/Umbraco.Web/Security/OwinDataProtectorTokenProvider.cs
index 15bd4dfd75..72e12b8621 100644
--- a/src/Umbraco.Web/Security/OwinDataProtectorTokenProvider.cs
+++ b/src/Umbraco.Web/Security/OwinDataProtectorTokenProvider.cs
@@ -5,7 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Owin.Security.DataProtection;
-using Umbraco.Web.Models.Identity;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/PreviewAuthenticationMiddleware.cs b/src/Umbraco.Web/Security/PreviewAuthenticationMiddleware.cs
index 2f9648d1f7..799edb5f60 100644
--- a/src/Umbraco.Web/Security/PreviewAuthenticationMiddleware.cs
+++ b/src/Umbraco.Web/Security/PreviewAuthenticationMiddleware.cs
@@ -1,12 +1,10 @@
using System.Security.Claims;
using System.Threading.Tasks;
-using System.Web;
using Microsoft.Owin;
using Umbraco.Core;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
-using Umbraco.Core.IO;
-using Umbraco.Core.Security;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/SessionIdValidator.cs b/src/Umbraco.Web/Security/SessionIdValidator.cs
index 9edae8da10..090b6c6dac 100644
--- a/src/Umbraco.Web/Security/SessionIdValidator.cs
+++ b/src/Umbraco.Web/Security/SessionIdValidator.cs
@@ -86,7 +86,7 @@ namespace Umbraco.Web.Security
if (validate == false)
return true;
- var manager = owinCtx.Get();
+ var manager = owinCtx.Get();
if (manager == null)
return false;
diff --git a/src/Umbraco.Web/Security/UmbracoSecureDataFormat.cs b/src/Umbraco.Web/Security/UmbracoSecureDataFormat.cs
index 19cd602657..41a2ad3bba 100644
--- a/src/Umbraco.Web/Security/UmbracoSecureDataFormat.cs
+++ b/src/Umbraco.Web/Security/UmbracoSecureDataFormat.cs
@@ -1,6 +1,6 @@
using System;
using Microsoft.Owin.Security;
-using Umbraco.Core.Security;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/UmbracoSecurityStampValidator.cs b/src/Umbraco.Web/Security/UmbracoSecurityStampValidator.cs
index a3f78f5262..18539d8fab 100644
--- a/src/Umbraco.Web/Security/UmbracoSecurityStampValidator.cs
+++ b/src/Umbraco.Web/Security/UmbracoSecurityStampValidator.cs
@@ -3,7 +3,7 @@ using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin.Security.Cookies;
using Umbraco.Core;
-using Umbraco.Web.Models.Identity;
+using Umbraco.Core.BackOffice;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/UserAwarePasswordHasher.cs b/src/Umbraco.Web/Security/UserAwarePasswordHasher.cs
index d804ef0ae4..b1d88348d0 100644
--- a/src/Umbraco.Web/Security/UserAwarePasswordHasher.cs
+++ b/src/Umbraco.Web/Security/UserAwarePasswordHasher.cs
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Identity;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Security;
-using Umbraco.Web.Models.Identity;
namespace Umbraco.Web.Security
{
diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs
index 8975f9cde0..6d3de9be1d 100644
--- a/src/Umbraco.Web/Security/WebSecurity.cs
+++ b/src/Umbraco.Web/Security/WebSecurity.cs
@@ -5,11 +5,10 @@ using Umbraco.Core;
using Umbraco.Core.Services;
using Umbraco.Core.Models.Membership;
using Microsoft.Owin;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
-using Umbraco.Core.IO;
using Umbraco.Core.Models;
-using Umbraco.Web.Models.Identity;
namespace Umbraco.Web.Security
{
@@ -71,8 +70,8 @@ namespace Umbraco.Web.Security
}
}
- private BackOfficeUserManager _userManager;
- protected BackOfficeUserManager UserManager
+ private BackOfficeOwinUserManager _userManager;
+ protected BackOfficeOwinUserManager UserManager
=> _userManager ?? (_userManager = _httpContextAccessor.GetRequiredHttpContext().GetOwinContext().GetBackOfficeUserManager());
[Obsolete("This needs to be removed, ASP.NET Identity should always be used for this operation, this is currently only used in the installer which needs to be updated")]
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index f8e73bb361..90d1d6829b 100755
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -173,10 +173,6 @@
-
-
-
-
@@ -194,23 +190,17 @@
-
-
+
-
-
-
-
-
diff --git a/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs b/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs
index c68b949bba..09fd5e080c 100644
--- a/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs
+++ b/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs
@@ -6,13 +6,12 @@ using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Umbraco.Core;
using Umbraco.Web.Composing;
-using Umbraco.Core.Models.Identity;
+using Umbraco.Core.BackOffice;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
using Umbraco.Web.Security;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
-using Umbraco.Web.Models.Identity;
namespace Umbraco.Web.WebApi.Filters
{
diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs
index 42e0fe2940..48b3de44fd 100644
--- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs
+++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs
@@ -2,10 +2,9 @@
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
-using Umbraco.Web.WebApi.Filters;using Umbraco.Core.Models.Identity;
+using Umbraco.Web.WebApi.Filters;
using Umbraco.Core.Persistence;
using Umbraco.Core.Services;
-using Umbraco.Web.Models.Identity;
using Umbraco.Web.Security;
using Umbraco.Core.Mapping;
using Umbraco.Web.Routing;
@@ -30,7 +29,7 @@ namespace Umbraco.Web.WebApi
[EnableDetailedErrors]
public abstract class UmbracoAuthorizedApiController : UmbracoApiController
{
- private BackOfficeUserManager _userManager;
+ private BackOfficeOwinUserManager _userManager;
protected UmbracoAuthorizedApiController()
{
@@ -44,7 +43,7 @@ namespace Umbraco.Web.WebApi
///
/// Gets the user manager.
///
- protected BackOfficeUserManager UserManager
+ protected BackOfficeOwinUserManager UserManager
=> _userManager ?? (_userManager = TryGetOwinContext().Result.GetBackOfficeUserManager());
}
}