diff --git a/src/Umbraco.Core/Models/Identity/IIdentityUser.cs b/src/Umbraco.Core/Models/Identity/IIdentityUser.cs new file mode 100644 index 0000000000..fa7f52c710 --- /dev/null +++ b/src/Umbraco.Core/Models/Identity/IIdentityUser.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Models.Identity +{ + public interface IIdentityUser + { + int AccessFailedCount { get; set; } + //ICollection Claims { get; } + string Email { get; set; } + bool EmailConfirmed { get; set; } + TKey Id { get; set; } + DateTime? LastLoginDateUtc { get; set; } + DateTime? LastPasswordChangeDateUtc { get; set; } + bool LockoutEnabled { get; set; } + DateTime? LockoutEndDateUtc { get; set; } + //ICollection Logins { get; } + string PasswordHash { get; set; } + string PhoneNumber { get; set; } + bool PhoneNumberConfirmed { get; set; } + //ICollection Roles { get; } + string SecurityStamp { get; set; } + bool TwoFactorEnabled { get; set; } + string UserName { get; set; } + } +} diff --git a/src/Umbraco.Core/Models/Identity/IIdentityUserLogin.cs b/src/Umbraco.Core/Models/Identity/IIdentityUserLogin.cs index cbe5b47b38..62c92de16d 100644 --- a/src/Umbraco.Core/Models/Identity/IIdentityUserLogin.cs +++ b/src/Umbraco.Core/Models/Identity/IIdentityUserLogin.cs @@ -1,27 +1,30 @@ -using Umbraco.Core.Models.Entities; +using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models.Identity { - + /// + /// An external login provider linked to a user + /// + /// The PK type for the user public interface IIdentityUserLogin : IEntity, IRememberBeingDirty { /// - /// The login provider for the login (i.e. Facebook, Google) + /// Gets or sets the login provider for the login (i.e. Facebook, Google) /// string LoginProvider { get; set; } /// - /// Key representing the login for the provider + /// Gets or sets key representing the login for the provider /// string ProviderKey { get; set; } /// - /// User Id for the user who owns this login + /// Gets or sets user Id for the user who owns this login /// int UserId { get; set; } /// - /// Used to store any arbitrary data for the user and external provider - like user tokens returned from the provider + /// Gets or sets any arbitrary data for the user and external provider - like user tokens returned from the provider /// string UserData { get; set; } } diff --git a/src/Umbraco.Core/Models/Identity/IdentityUser.cs b/src/Umbraco.Core/Models/Identity/IdentityUser.cs index 093e42c1e7..dd3841d2c8 100644 --- a/src/Umbraco.Core/Models/Identity/IdentityUser.cs +++ b/src/Umbraco.Core/Models/Identity/IdentityUser.cs @@ -1,26 +1,30 @@ -using System; +using System; using System.Collections.Generic; namespace Umbraco.Core.Models.Identity { /// - /// Default IUser implementation + /// Abstract class for use in Umbraco Identity /// - /// + /// The type of user login + /// The type of user role + /// The type of user claims /// - /// This class normally exists inside of the EntityFramework library, not sure why MS chose to explicitly put it there but we don't want - /// references to that so we will create our own here + /// This class was originally borrowed from the EF implementation in Identity prior to netcore. + /// The new IdentityUser in netcore does not have properties such as Claims, Roles and Logins and those are instead + /// by default managed with their default user store backed by EF which utilizes EF's change tracking to track these values + /// to a user. We will continue using this approach since it works fine for what we need which does the change tracking of + /// claims, roles and logins directly on the user model. /// - public class IdentityUser + public abstract class IdentityUser where TLogin : IIdentityUserLogin - //NOTE: Making our role id a string - where TRole : IdentityUserRole - where TClaim : IdentityUserClaim + where TRole : IdentityUserRole + where TClaim : IdentityUserClaim { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public IdentityUser() + protected IdentityUser() { Claims = new List(); Roles = new List(); @@ -28,87 +32,96 @@ namespace Umbraco.Core.Models.Identity } /// - /// Last login date + /// Gets or sets last login date /// public virtual DateTime? LastLoginDateUtc { get; set; } /// - /// Email + /// Gets or sets email /// public virtual string Email { get; set; } /// - /// True if the email is confirmed, default is false + /// Gets or sets a value indicating whether the email is confirmed, default is false /// public virtual bool EmailConfirmed { get; set; } /// - /// The salted/hashed form of the user password + /// Gets or sets the salted/hashed form of the user password /// public virtual string PasswordHash { get; set; } /// - /// A random value that should change whenever a users credentials have changed (password changed, login removed) + /// Gets or sets a random value that should change whenever a users credentials have changed (password changed, login removed) /// public virtual string SecurityStamp { get; set; } /// - /// PhoneNumber for the user + /// Gets or sets a phone Number for the user /// + /// + /// This is unused until we or an end-user requires this value for 2FA + /// public virtual string PhoneNumber { get; set; } /// - /// True if the phone number is confirmed, default is false + /// Gets or sets a value indicating whether true if the phone number is confirmed, default is false /// + /// + /// This is unused until we or an end-user requires this value for 2FA + /// public virtual bool PhoneNumberConfirmed { get; set; } /// - /// Is two factor enabled for the user + /// Gets or sets a value indicating whether is two factor enabled for the user /// + /// + /// This is unused until we or an end-user requires this value for 2FA + /// public virtual bool TwoFactorEnabled { get; set; } /// - /// DateTime in UTC when lockout ends, any time in the past is considered not locked out. + /// Gets or sets dateTime in UTC when lockout ends, any time in the past is considered not locked out. /// public virtual DateTime? LockoutEndDateUtc { get; set; } /// - /// DateTime in UTC when the password was last changed. + /// Gets or sets dateTime in UTC when the password was last changed. /// public virtual DateTime? LastPasswordChangeDateUtc { get; set; } /// - /// Is lockout enabled for this user + /// Gets or sets a value indicating whether is lockout enabled for this user /// public virtual bool LockoutEnabled { get; set; } /// - /// Used to record failures for the purposes of lockout + /// Gets or sets the value to record failures for the purposes of lockout /// public virtual int AccessFailedCount { get; set; } /// - /// Navigation property for user roles + /// Gets the user roles collection /// public virtual ICollection Roles { get; } /// - /// Navigation property for user claims + /// Gets navigation the user claims collection /// public virtual ICollection Claims { get; } /// - /// Navigation property for user logins + /// Gets the user logins collection /// public virtual ICollection Logins { get; } /// - /// User ID (Primary Key) + /// Gets or sets user ID (Primary Key) /// - public virtual TKey Id { get; set; } + public virtual int Id { get; set; } /// - /// User name + /// Gets or sets user name /// public virtual string UserName { get; set; } } diff --git a/src/Umbraco.Core/Models/Identity/IdentityUserClaim.cs b/src/Umbraco.Core/Models/Identity/IdentityUserClaim.cs index e117d2fd13..2524463284 100644 --- a/src/Umbraco.Core/Models/Identity/IdentityUserClaim.cs +++ b/src/Umbraco.Core/Models/Identity/IdentityUserClaim.cs @@ -1,37 +1,27 @@ -namespace Umbraco.Core.Models.Identity +namespace Umbraco.Core.Models.Identity { /// /// EntityType that represents one specific user claim - /// /// - /// - /// - /// This class normally exists inside of the EntityFramework library, not sure why MS chose to explicitly put it there but we don't want - /// references to that so we will create our own here - /// - public class IdentityUserClaim + public class IdentityUserClaim { /// - /// Primary key - /// + /// Gets or sets primary key /// - public virtual int Id { get; set; } + public virtual string Id { get; set; } // TODO: Not used /// - /// User Id for the user who owns this login - /// + /// Gets or sets user Id for the user who owns this login /// - public virtual TKey UserId { get; set; } + public virtual string UserId { get; set; } /// - /// Claim type - /// + /// Gets or sets claim type /// public virtual string ClaimType { get; set; } /// - /// Claim value - /// + /// Gets or sets claim value /// public virtual string ClaimValue { get; set; } } diff --git a/src/Umbraco.Core/Models/Identity/IdentityUserLogin.cs b/src/Umbraco.Core/Models/Identity/IdentityUserLogin.cs index c13b28461d..18e8d4694b 100644 --- a/src/Umbraco.Core/Models/Identity/IdentityUserLogin.cs +++ b/src/Umbraco.Core/Models/Identity/IdentityUserLogin.cs @@ -1,4 +1,4 @@ -using System; +using System; using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models.Identity diff --git a/src/Umbraco.Core/Models/Identity/IdentityUserRole.cs b/src/Umbraco.Core/Models/Identity/IdentityUserRole.cs index ba9e87e46c..39ed65112d 100644 --- a/src/Umbraco.Core/Models/Identity/IdentityUserRole.cs +++ b/src/Umbraco.Core/Models/Identity/IdentityUserRole.cs @@ -1,26 +1,19 @@ -namespace Umbraco.Core.Models.Identity +namespace Umbraco.Core.Models.Identity { /// /// EntityType that represents a user belonging to a role - /// /// /// - /// - /// This class normally exists inside of the EntityFramework library, not sure why MS chose to explicitly put it there but we don't want - /// references to that so we will create our own here - /// - public class IdentityUserRole + public class IdentityUserRole { /// - /// UserId for the user that is in the role - /// + /// Gets or sets userId for the user that is in the role /// - public virtual TKey UserId { get; set; } + public virtual string UserId { get; set; } /// - /// RoleId for the role - /// + /// Gets or sets roleId for the role /// - public virtual TKey RoleId { get; set; } + public virtual string RoleId { get; set; } } } diff --git a/src/Umbraco.Core/Security/AuthenticationExtensions.cs b/src/Umbraco.Core/Security/AuthenticationExtensions.cs index edc11bcac2..607c4748cc 100644 --- a/src/Umbraco.Core/Security/AuthenticationExtensions.cs +++ b/src/Umbraco.Core/Security/AuthenticationExtensions.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.Security.Principal; using System.Text; using System.Threading; -using Umbraco.Core.BackOffice; namespace Umbraco.Core.Security { diff --git a/src/Umbraco.Core/BackOffice/BackOfficeIdentityUser.cs b/src/Umbraco.Core/Security/BackOfficeIdentityUser.cs similarity index 90% rename from src/Umbraco.Core/BackOffice/BackOfficeIdentityUser.cs rename to src/Umbraco.Core/Security/BackOfficeIdentityUser.cs index 027e7c0904..e8e036b51b 100644 --- a/src/Umbraco.Core/BackOffice/BackOfficeIdentityUser.cs +++ b/src/Umbraco.Core/Security/BackOfficeIdentityUser.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; @@ -10,14 +10,13 @@ using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Identity; using Umbraco.Core.Models.Membership; -namespace Umbraco.Core.BackOffice +namespace Umbraco.Core.Security { - public class BackOfficeIdentityUser : IdentityUser, IdentityUserClaim>, IRememberBeingDirty + public class BackOfficeIdentityUser : IdentityUser, IRememberBeingDirty { private string _email; private string _userName; private int _id; - private bool _hasIdentity; private DateTime? _lastLoginDateUtc; private bool _emailConfirmed; private string _name; @@ -36,23 +35,32 @@ namespace Umbraco.Core.BackOffice /// /// Used to construct a new instance without an identity /// + /// /// /// This is allowed to be null (but would need to be filled in if trying to persist this instance) /// /// public static BackOfficeIdentityUser CreateNew(GlobalSettings globalSettings, string username, string email, string culture, string name = null) { - if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(username)); - if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture)); + if (string.IsNullOrWhiteSpace(username)) + { + throw new ArgumentException("Value cannot be null or whitespace.", nameof(username)); + } + + if (string.IsNullOrWhiteSpace(culture)) + { + throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture)); + } var user = new BackOfficeIdentityUser(globalSettings, Array.Empty()); user.DisableChangeTracking(); user._userName = username; user._email = email; - //we are setting minvalue here because the default is "0" which is the id of the admin user - //which we cannot allow because the admin user will always exist + + // we are setting minvalue here because the default is "0" which is the id of the admin user + // which we cannot allow because the admin user will always exist user._id = int.MinValue; - user._hasIdentity = false; + user.HasIdentity = false; user._culture = culture; user._name = name; user.EnableChangeTracking(); @@ -67,7 +75,7 @@ namespace Umbraco.Core.BackOffice _culture = globalSettings.DefaultUILanguage; // must initialize before setting groups - _roles = new ObservableCollection>(); + _roles = new ObservableCollection(); _roles.CollectionChanged += _roles_CollectionChanged; // use the property setters - they do more than just setting a field @@ -75,7 +83,7 @@ namespace Umbraco.Core.BackOffice } /// - /// Creates an existing user with the specified groups + /// Initializes a new instance of the class. /// /// /// @@ -90,7 +98,7 @@ namespace Umbraco.Core.BackOffice /// /// Returns true if an Id has been set on this object this will be false if the object is new and not persisted to the database /// - public bool HasIdentity => _hasIdentity; + public bool HasIdentity { get; private set; } public int[] CalculatedMediaStartNodeIds { get; set; } public int[] CalculatedContentStartNodeIds { get; set; } @@ -101,7 +109,7 @@ namespace Umbraco.Core.BackOffice set { _id = value; - _hasIdentity = true; + HasIdentity = true; } } @@ -192,7 +200,8 @@ namespace Umbraco.Core.BackOffice get => _startContentIds; set { - if (value == null) value = new int[0]; + if (value == null) + value = new int[0]; _beingDirty.SetPropertyValueAndDetectChanges(value, ref _startContentIds, nameof(StartContentIds), StartIdsComparer); } } @@ -205,7 +214,8 @@ namespace Umbraco.Core.BackOffice get => _startMediaIds; set { - if (value == null) value = new int[0]; + if (value == null) + value = new int[0]; _beingDirty.SetPropertyValueAndDetectChanges(value, ref _startMediaIds, nameof(StartMediaIds), StartIdsComparer); } } @@ -237,7 +247,7 @@ namespace Umbraco.Core.BackOffice //now clear all roles and re-add them _roles.CollectionChanged -= _roles_CollectionChanged; _roles.Clear(); - foreach (var identityUserRole in _groups.Select(x => new IdentityUserRole + foreach (var identityUserRole in _groups.Select(x => new IdentityUserRole { RoleId = x.Alias, UserId = Id.ToString() @@ -288,7 +298,8 @@ namespace Umbraco.Core.BackOffice get { // return if it exists - if (_logins != null) return _logins; + if (_logins != null) + return _logins; _logins = new ObservableCollection(); @@ -318,7 +329,7 @@ namespace Umbraco.Core.BackOffice _beingDirty.OnPropertyChanged(nameof(Roles)); } - private readonly ObservableCollection> _roles; + private readonly ObservableCollection _roles; /// /// helper method to easily add a role without having to deal with IdentityUserRole{T} @@ -329,7 +340,7 @@ namespace Umbraco.Core.BackOffice /// public void AddRole(string role) { - Roles.Add(new IdentityUserRole + Roles.Add(new IdentityUserRole { UserId = Id.ToString(), RoleId = role @@ -339,7 +350,7 @@ namespace Umbraco.Core.BackOffice /// /// Override Roles because the value of these are the user's group aliases /// - public override ICollection> Roles => _roles; + public override ICollection Roles => _roles; /// /// Used to set a lazy call back to populate the user's Login list diff --git a/src/Umbraco.Core/BackOffice/BackOfficeUserPasswordCheckerResult.cs b/src/Umbraco.Core/Security/BackOfficeUserPasswordCheckerResult.cs similarity index 87% rename from src/Umbraco.Core/BackOffice/BackOfficeUserPasswordCheckerResult.cs rename to src/Umbraco.Core/Security/BackOfficeUserPasswordCheckerResult.cs index 7936fab682..c640c85d0c 100644 --- a/src/Umbraco.Core/BackOffice/BackOfficeUserPasswordCheckerResult.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserPasswordCheckerResult.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.BackOffice +namespace Umbraco.Core.Security { /// /// The result returned from the IBackOfficeUserPasswordChecker diff --git a/src/Umbraco.Core/BackOffice/ClaimsPrincipalExtensions.cs b/src/Umbraco.Core/Security/ClaimsPrincipalExtensions.cs similarity index 98% rename from src/Umbraco.Core/BackOffice/ClaimsPrincipalExtensions.cs rename to src/Umbraco.Core/Security/ClaimsPrincipalExtensions.cs index 7cbca0428a..395465cfb7 100644 --- a/src/Umbraco.Core/BackOffice/ClaimsPrincipalExtensions.cs +++ b/src/Umbraco.Core/Security/ClaimsPrincipalExtensions.cs @@ -1,10 +1,10 @@ -using System; +using System; using System.Globalization; using System.Linq; using System.Security.Claims; using System.Security.Principal; using Umbraco.Core; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Extensions { diff --git a/src/Umbraco.Core/BackOffice/IBackOfficeUserPasswordChecker.cs b/src/Umbraco.Core/Security/IBackOfficeUserPasswordChecker.cs similarity index 93% rename from src/Umbraco.Core/BackOffice/IBackOfficeUserPasswordChecker.cs rename to src/Umbraco.Core/Security/IBackOfficeUserPasswordChecker.cs index 5874337f4a..45f5ea44e2 100644 --- a/src/Umbraco.Core/BackOffice/IBackOfficeUserPasswordChecker.cs +++ b/src/Umbraco.Core/Security/IBackOfficeUserPasswordChecker.cs @@ -1,6 +1,6 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; -namespace Umbraco.Core.BackOffice +namespace Umbraco.Core.Security { /// /// Used by the BackOfficeUserManager to check the username/password which allows for developers to more easily diff --git a/src/Umbraco.Core/BackOffice/IdentityAuditEventArgs.cs b/src/Umbraco.Core/Security/IdentityAuditEventArgs.cs similarity index 96% rename from src/Umbraco.Core/BackOffice/IdentityAuditEventArgs.cs rename to src/Umbraco.Core/Security/IdentityAuditEventArgs.cs index 1d51c45074..454d651944 100644 --- a/src/Umbraco.Core/BackOffice/IdentityAuditEventArgs.cs +++ b/src/Umbraco.Core/Security/IdentityAuditEventArgs.cs @@ -1,7 +1,7 @@ -using System; +using System; -namespace Umbraco.Core.BackOffice +namespace Umbraco.Core.Security { /// @@ -58,7 +58,7 @@ namespace Umbraco.Core.BackOffice DateTimeUtc = DateTime.UtcNow; Action = action; IpAddress = ipAddress; - Comment = comment; + Comment = comment; PerformingUser = performingUser; AffectedUsername = affectedUsername; AffectedUser = affectedUser; diff --git a/src/Umbraco.Core/BackOffice/IdentityMapDefinition.cs b/src/Umbraco.Core/Security/IdentityMapDefinition.cs similarity index 97% rename from src/Umbraco.Core/BackOffice/IdentityMapDefinition.cs rename to src/Umbraco.Core/Security/IdentityMapDefinition.cs index 61fdf82d19..26a5d11f6e 100644 --- a/src/Umbraco.Core/BackOffice/IdentityMapDefinition.cs +++ b/src/Umbraco.Core/Security/IdentityMapDefinition.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; @@ -7,7 +7,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; -namespace Umbraco.Core.BackOffice +namespace Umbraco.Core.Security { public class IdentityMapDefinition : IMapDefinition { @@ -65,7 +65,7 @@ namespace Umbraco.Core.BackOffice target.Culture = source.GetUserCulture(_textService, _globalSettings).ToString(); // project CultureInfo to string target.IsApproved = source.IsApproved; target.SecurityStamp = source.SecurityStamp; - target.LockoutEndDateUtc = source.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null; + target.LockoutEndDateUtc = source.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?)null; // this was in AutoMapper but does not have a setter anyways //target.AllowedSections = source.AllowedSections.ToArray(), diff --git a/src/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentity.cs b/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs similarity index 85% rename from src/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentity.cs rename to src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs index 9a60c5d64f..3430814f83 100644 --- a/src/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentity.cs +++ b/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs @@ -1,9 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; -namespace Umbraco.Core.BackOffice +namespace Umbraco.Core.Security { /// @@ -15,13 +15,12 @@ namespace Umbraco.Core.BackOffice // TODO: Ideally we remove this class and only deal with ClaimsIdentity as a best practice. All things relevant to our own // identity are part of claims. This class would essentially become extension methods on a ClaimsIdentity for resolving // values from it. - public static bool FromClaimsIdentity(ClaimsIdentity identity, out UmbracoBackOfficeIdentity backOfficeIdentity) { - //validate that all claims exist + // validate that all claims exist foreach (var t in RequiredBackOfficeIdentityClaimTypes) { - //if the identity doesn't have the claim, or the claim value is null + // if the identity doesn't have the claim, or the claim value is null if (identity.HasClaim(x => x.Type == t) == false || identity.HasClaim(x => x.Type == t && x.Value.IsNullOrWhiteSpace())) { backOfficeIdentity = null; @@ -59,11 +58,16 @@ namespace Umbraco.Core.BackOffice string securityStamp, IEnumerable allowedApps, IEnumerable roles) : base(Enumerable.Empty(), Constants.Security.BackOfficeAuthenticationType) //this ctor is used to ensure the IsAuthenticated property is true { - if (allowedApps == null) throw new ArgumentNullException(nameof(allowedApps)); - if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(username)); - if (string.IsNullOrWhiteSpace(realName)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(realName)); - if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture)); - if (string.IsNullOrWhiteSpace(securityStamp)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(securityStamp)); + if (allowedApps == null) + throw new ArgumentNullException(nameof(allowedApps)); + if (string.IsNullOrWhiteSpace(username)) + throw new ArgumentException("Value cannot be null or whitespace.", nameof(username)); + if (string.IsNullOrWhiteSpace(realName)) + throw new ArgumentException("Value cannot be null or whitespace.", nameof(realName)); + if (string.IsNullOrWhiteSpace(culture)) + throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture)); + if (string.IsNullOrWhiteSpace(securityStamp)) + throw new ArgumentException("Value cannot be null or whitespace.", nameof(securityStamp)); AddRequiredClaims(userId, username, realName, startContentNodes, startMediaNodes, culture, securityStamp, allowedApps, roles); } @@ -88,10 +92,14 @@ namespace Umbraco.Core.BackOffice string securityStamp, IEnumerable allowedApps, IEnumerable roles) : base(childIdentity.Claims, Constants.Security.BackOfficeAuthenticationType) { - if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(username)); - if (string.IsNullOrWhiteSpace(realName)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(realName)); - if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture)); - if (string.IsNullOrWhiteSpace(securityStamp)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(securityStamp)); + if (string.IsNullOrWhiteSpace(username)) + throw new ArgumentException("Value cannot be null or whitespace.", nameof(username)); + if (string.IsNullOrWhiteSpace(realName)) + throw new ArgumentException("Value cannot be null or whitespace.", nameof(realName)); + if (string.IsNullOrWhiteSpace(culture)) + throw new ArgumentException("Value cannot be null or whitespace.", nameof(culture)); + if (string.IsNullOrWhiteSpace(securityStamp)) + throw new ArgumentException("Value cannot be null or whitespace.", nameof(securityStamp)); AddRequiredClaims(userId, username, realName, startContentNodes, startMediaNodes, culture, securityStamp, allowedApps, roles); } @@ -205,7 +213,7 @@ namespace Umbraco.Core.BackOffice public string SecurityStamp => this.FindFirstValue(Constants.Security.SecurityStampClaimType); - public string[] Roles => this.FindAll(x => x.Type == DefaultRoleClaimType).Select(role => role.Value).ToArray(); + public string[] Roles => FindAll(x => x.Type == DefaultRoleClaimType).Select(role => role.Value).ToArray(); /// /// Overridden to remove any temporary claims that shouldn't be copied diff --git a/src/Umbraco.Infrastructure/BackOffice/BackOfficeClaimsPrincipalFactory.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeClaimsPrincipalFactory.cs index 22ea4423d2..380ed452d0 100644 --- a/src/Umbraco.Infrastructure/BackOffice/BackOfficeClaimsPrincipalFactory.cs +++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeClaimsPrincipalFactory.cs @@ -4,6 +4,7 @@ using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; +using Umbraco.Core.Security; namespace Umbraco.Core.BackOffice { @@ -36,11 +37,13 @@ namespace Umbraco.Core.BackOffice ClaimsIdentity baseIdentity = await base.GenerateClaimsAsync(user); + // TODO: How to flow claims then? This is most likely built into aspnetcore now and this is not the way + // now we can flow any custom claims that the actual user has currently assigned which could be done in the OnExternalLogin callback - foreach (Models.Identity.IdentityUserClaim claim in user.Claims) - { - baseIdentity.AddClaim(new Claim(claim.ClaimType, claim.ClaimValue)); - } + //foreach (Models.Identity.IdentityUserClaim claim in user.Claims) + //{ + // baseIdentity.AddClaim(new Claim(claim.ClaimType, claim.ClaimValue)); + //} // TODO: We want to remove UmbracoBackOfficeIdentity and only rely on ClaimsIdentity, once // that is done then we'll create a ClaimsIdentity with all of the requirements here instead diff --git a/src/Umbraco.Infrastructure/BackOffice/BackOfficeIdentityBuilder.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeIdentityBuilder.cs index 5bae03cad6..90c2823122 100644 --- a/src/Umbraco.Infrastructure/BackOffice/BackOfficeIdentityBuilder.cs +++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeIdentityBuilder.cs @@ -3,6 +3,7 @@ using System.Reflection; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Infrastructure.BackOffice { diff --git a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs index b271f5aa41..e297eca86d 100644 --- a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs +++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Data; using System.Linq; @@ -13,6 +13,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; using Umbraco.Core.Models.Membership; using Umbraco.Core.Scoping; +using Umbraco.Core.Security; using Umbraco.Core.Services; namespace Umbraco.Core.BackOffice @@ -23,7 +24,7 @@ namespace Umbraco.Core.BackOffice IUserLoginStore, IUserRoleStore, IUserSecurityStampStore, - IUserLockoutStore, + IUserLockoutStore, IUserSessionStore // TODO: This would require additional columns/tables and then a lot of extra coding support to make this happen natively within umbraco diff --git a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserValidator.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserValidator.cs index 131bd08ac9..b7cbb7555d 100644 --- a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserValidator.cs +++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserValidator.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Umbraco.Core.Security; namespace Umbraco.Core.BackOffice { diff --git a/src/Umbraco.Infrastructure/BackOffice/IBackOfficeUserManager.cs b/src/Umbraco.Infrastructure/BackOffice/IBackOfficeUserManager.cs index c026c256f5..be4bd194f9 100644 --- a/src/Umbraco.Infrastructure/BackOffice/IBackOfficeUserManager.cs +++ b/src/Umbraco.Infrastructure/BackOffice/IBackOfficeUserManager.cs @@ -1,324 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Security.Principal; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity; -using Umbraco.Core.Models.Membership; -using Umbraco.Web.Models.ContentEditing; +using Umbraco.Core.Security; namespace Umbraco.Core.BackOffice { - public interface IBackOfficeUserManager : IBackOfficeUserManager + /// + /// The user manager for the back office + /// + public interface IBackOfficeUserManager : IUmbracoUserManager { - - } - public interface IBackOfficeUserManager: IDisposable - where TUser : BackOfficeIdentityUser - { - Task GetUserIdAsync(TUser user); - - Task GetUserAsync(ClaimsPrincipal principal); - - string GetUserId(ClaimsPrincipal principal); - - Task> GetLoginsAsync(TUser user); - - Task DeleteAsync(TUser user); - - Task FindByLoginAsync(string loginProvider, string providerKey); - - /// - /// Finds and returns a user, if any, who has the specified . - /// - /// The user ID to search for. - /// - /// The that represents the asynchronous operation, containing the user matching the specified if it exists. - /// - Task FindByIdAsync(string userId); - - /// - /// Generates a password reset token for the specified , using - /// the configured password reset token provider. - /// - /// The user to generate a password reset token for. - /// The that represents the asynchronous operation, - /// containing a password reset token for the specified . - Task GeneratePasswordResetTokenAsync(TUser user); - - /// - /// This is a special method that will reset the password but will raise the Password Changed event instead of the reset event - /// - /// - /// - /// - /// - /// - /// We use this because in the back office the only way an admin can change another user's password without first knowing their password - /// is to generate a token and reset it, however, when we do this we want to track a password change, not a password reset - /// - Task ChangePasswordWithResetAsync(int userId, string token, string newPassword); - - /// - /// Validates that an email confirmation token matches the specified . - /// - /// The user to validate the token against. - /// The email confirmation token to validate. - /// - /// The that represents the asynchronous operation, containing the - /// of the operation. - /// - Task ConfirmEmailAsync(TUser user, string token); - - /// - /// Gets the user, if any, associated with the normalized value of the specified email address. - /// Note: Its recommended that identityOptions.User.RequireUniqueEmail be set to true when using this method, otherwise - /// the store may throw if there are users with duplicate emails. - /// - /// The email address to return the user for. - /// - /// The task object containing the results of the asynchronous lookup operation, the user, if any, associated with a normalized value of the specified email address. - /// - Task FindByEmailAsync(string email); - - /// - /// Resets the 's password to the specified after - /// validating the given password reset . - /// - /// The user whose password should be reset. - /// The password reset token to verify. - /// The new password to set if reset token verification succeeds. - /// - /// The that represents the asynchronous operation, containing the - /// of the operation. - /// - Task ResetPasswordAsync(TUser user, string token, string newPassword); - - /// - /// Override to check the user approval value as well as the user lock out date, by default this only checks the user's locked out date - /// - /// - /// - /// - /// In the ASP.NET Identity world, there is only one value for being locked out, in Umbraco we have 2 so when checking this for Umbraco we need to check both values - /// - Task IsLockedOutAsync(TUser user); - - /// - /// Locks out a user until the specified end date has passed. Setting a end date in the past immediately unlocks a user. - /// - /// The user whose lockout date should be set. - /// The after which the 's lockout should end. - /// The that represents the asynchronous operation, containing the of the operation. - Task SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd); - - /// - /// Gets a flag indicating whether the email address for the specified has been verified, true if the email address is verified otherwise - /// false. - /// - /// The user whose email confirmation status should be returned. - /// - /// The task object containing the results of the asynchronous operation, a flag indicating whether the email address for the specified - /// has been confirmed or not. - /// - Task IsEmailConfirmedAsync(TUser user); - - /// - /// Updates the specified in the backing store. - /// - /// The user to update. - /// - /// The that represents the asynchronous operation, containing the - /// of the operation. - /// - Task UpdateAsync(TUser user); - - /// - /// Returns a flag indicating whether the specified is valid for - /// the given and . - /// - /// The user to validate the token against. - /// The token provider used to generate the token. - /// The purpose the token should be generated for. - /// The token to validate - /// - /// The that represents the asynchronous operation, returning true if the - /// is valid, otherwise false. - /// - Task VerifyUserTokenAsync(TUser user, string tokenProvider, string purpose, - string token); - - /// - /// Adds the to the specified only if the user - /// does not already have a password. - /// - /// The user whose password should be set. - /// The password to set. - /// - /// The that represents the asynchronous operation, containing the - /// of the operation. - /// - Task AddPasswordAsync(TUser user, string password); - - - /// - /// Returns a flag indicating whether the given is valid for the - /// specified . - /// - /// The user whose password should be validated. - /// The password to validate - /// The that represents the asynchronous operation, containing true if - /// the specified matches the one store for the , - /// otherwise false. - Task CheckPasswordAsync(TUser user, string password); - - /// - /// Changes a user's password after confirming the specified is correct, - /// as an asynchronous operation. - /// - /// The user whose password should be set. - /// The current password to validate before changing. - /// The new password to set for the specified . - /// - /// The that represents the asynchronous operation, containing the - /// of the operation. - /// - Task ChangePasswordAsync(TUser user, string currentPassword, - string newPassword); - - /// - /// Used to validate a user's session - /// - /// - /// - /// - Task ValidateSessionIdAsync(string userId, string sessionId); - - /// - /// Creates the specified in the backing store with no password, - /// as an asynchronous operation. - /// - /// The user to create. - /// - /// The that represents the asynchronous operation, containing the - /// of the operation. - /// - Task CreateAsync(TUser user); - - /// - /// Helper method to generate a password for a user based on the current password validator - /// - /// - string GeneratePassword(); - - - /// - /// Generates an email confirmation token for the specified user. - /// - /// The user to generate an email confirmation token for. - /// - /// The that represents the asynchronous operation, an email confirmation token. - /// - Task GenerateEmailConfirmationTokenAsync(TUser user); - - /// - /// Finds and returns a user, if any, who has the specified user name. - /// - /// The user name to search for. - /// - /// The that represents the asynchronous operation, containing the user matching the specified if it exists. - /// - Task FindByNameAsync(string userName); - - /// - /// Increments the access failed count for the user as an asynchronous operation. - /// If the failed access account is greater than or equal to the configured maximum number of attempts, - /// the user will be locked out for the configured lockout time span. - /// - /// The user whose failed access count to increment. - /// The that represents the asynchronous operation, containing the of the operation. - Task AccessFailedAsync(TUser user); - - /// - /// Returns a flag indicating whether the specified has two factor authentication enabled or not, - /// as an asynchronous operation. - /// - /// The user whose two factor authentication enabled status should be retrieved. - /// - /// The that represents the asynchronous operation, true if the specified - /// has two factor authentication enabled, otherwise false. - /// - Task GetTwoFactorEnabledAsync(TUser user); - - /// - /// Gets a list of valid two factor token providers for the specified , - /// as an asynchronous operation. - /// - /// The user the whose two factor authentication providers will be returned. - /// - /// The that represents result of the asynchronous operation, a list of two - /// factor authentication providers for the specified user. - /// - Task> GetValidTwoFactorProvidersAsync(TUser user); - - /// - /// Verifies the specified two factor authentication against the . - /// - /// The user the token is supposed to be for. - /// The provider which will verify the token. - /// The token to verify. - /// - /// The that represents result of the asynchronous operation, true if the token is valid, - /// otherwise false. - /// - Task VerifyTwoFactorTokenAsync(TUser user, string tokenProvider, string token); - - /// - /// Adds an external Microsoft.AspNetCore.Identity.UserLoginInfo to the specified user. - /// - /// The user to add the login to. - /// The external Microsoft.AspNetCore.Identity.UserLoginInfo to add to the specified user. - /// The System.Threading.Tasks.Task that represents the asynchronous operation, containing the Microsoft.AspNetCore.Identity.IdentityResult of the operation. - Task AddLoginAsync(TUser user, UserLoginInfo login); - - /// - /// Attempts to remove the provided external login information from the specified user. and returns a flag indicating whether the removal succeed or not. - /// - /// The user to remove the login information from. - /// The login provide whose information should be removed. - /// The key given by the external login provider for the specified user. - /// The System.Threading.Tasks.Task that represents the asynchronous operation, containing the Microsoft.AspNetCore.Identity.IdentityResult of the operation. - Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey); - - Task ResetAccessFailedCountAsync(TUser user); - - Task GenerateTwoFactorTokenAsync(TUser user, string tokenProvider); - - /// - /// Gets the email address for the specified user. - /// - /// The user whose email should be returned. - /// The task object containing the results of the asynchronous operation, the email address for the specified user. - Task GetEmailAsync(TUser user); - - /// - /// Gets the telephone number, if any, for the specified user. - /// - /// The user whose telephone number should be retrieved. - /// The System.Threading.Tasks.Task that represents the asynchronous operation, containing the user's telephone number, if any. - /// - /// A user can only support a phone number if the BackOfficeUserStore is replaced with another that implements IUserPhoneNumberStore - /// - Task GetPhoneNumberAsync(TUser user); - - // TODO: These are raised from outside the signinmanager and usermanager in the auth and user controllers, - // let's see if there's a way to avoid that and only have these called within signinmanager and usermanager - // which means we can remove these from the interface (things like invite seems like they cannot be moved) - void RaiseForgotPasswordRequestedEvent(IPrincipal currentUser, int userId); - void RaiseForgotPasswordChangedSuccessEvent(IPrincipal currentUser, int userId); - SignOutAuditEventArgs RaiseLogoutSuccessEvent(IPrincipal currentUser, int userId); - UserInviteEventArgs RaiseSendingUserInvite(IPrincipal currentUser, UserInvite invite, IUser createdUser); - bool HasSendingUserInviteEventHandler { get; } - } } diff --git a/src/Umbraco.Infrastructure/BackOffice/IUmbracoUserManager.cs b/src/Umbraco.Infrastructure/BackOffice/IUmbracoUserManager.cs new file mode 100644 index 0000000000..8f8e0ffc50 --- /dev/null +++ b/src/Umbraco.Infrastructure/BackOffice/IUmbracoUserManager.cs @@ -0,0 +1,326 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Security.Principal; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Core.BackOffice +{ + + /// + /// A user manager for Umbraco (either back office users or front-end members) + /// + /// The type of user + public interface IUmbracoUserManager : IDisposable + where TUser : BackOfficeIdentityUser + { + Task GetUserIdAsync(TUser user); + + Task GetUserAsync(ClaimsPrincipal principal); + + string GetUserId(ClaimsPrincipal principal); + + Task> GetLoginsAsync(TUser user); + + Task DeleteAsync(TUser user); + + Task FindByLoginAsync(string loginProvider, string providerKey); + + /// + /// Finds and returns a user, if any, who has the specified . + /// + /// The user ID to search for. + /// + /// The that represents the asynchronous operation, containing the user matching the specified if it exists. + /// + Task FindByIdAsync(string userId); + + /// + /// Generates a password reset token for the specified , using + /// the configured password reset token provider. + /// + /// The user to generate a password reset token for. + /// The that represents the asynchronous operation, + /// containing a password reset token for the specified . + Task GeneratePasswordResetTokenAsync(TUser user); + + /// + /// This is a special method that will reset the password but will raise the Password Changed event instead of the reset event + /// + /// + /// + /// + /// + /// + /// We use this because in the back office the only way an admin can change another user's password without first knowing their password + /// is to generate a token and reset it, however, when we do this we want to track a password change, not a password reset + /// + Task ChangePasswordWithResetAsync(int userId, string token, string newPassword); + + /// + /// Validates that an email confirmation token matches the specified . + /// + /// The user to validate the token against. + /// The email confirmation token to validate. + /// + /// The that represents the asynchronous operation, containing the + /// of the operation. + /// + Task ConfirmEmailAsync(TUser user, string token); + + /// + /// Gets the user, if any, associated with the normalized value of the specified email address. + /// Note: Its recommended that identityOptions.User.RequireUniqueEmail be set to true when using this method, otherwise + /// the store may throw if there are users with duplicate emails. + /// + /// The email address to return the user for. + /// + /// The task object containing the results of the asynchronous lookup operation, the user, if any, associated with a normalized value of the specified email address. + /// + Task FindByEmailAsync(string email); + + /// + /// Resets the 's password to the specified after + /// validating the given password reset . + /// + /// The user whose password should be reset. + /// The password reset token to verify. + /// The new password to set if reset token verification succeeds. + /// + /// The that represents the asynchronous operation, containing the + /// of the operation. + /// + Task ResetPasswordAsync(TUser user, string token, string newPassword); + + /// + /// Override to check the user approval value as well as the user lock out date, by default this only checks the user's locked out date + /// + /// + /// + /// + /// In the ASP.NET Identity world, there is only one value for being locked out, in Umbraco we have 2 so when checking this for Umbraco we need to check both values + /// + Task IsLockedOutAsync(TUser user); + + /// + /// Locks out a user until the specified end date has passed. Setting a end date in the past immediately unlocks a user. + /// + /// The user whose lockout date should be set. + /// The after which the 's lockout should end. + /// The that represents the asynchronous operation, containing the of the operation. + Task SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd); + + /// + /// Gets a flag indicating whether the email address for the specified has been verified, true if the email address is verified otherwise + /// false. + /// + /// The user whose email confirmation status should be returned. + /// + /// The task object containing the results of the asynchronous operation, a flag indicating whether the email address for the specified + /// has been confirmed or not. + /// + Task IsEmailConfirmedAsync(TUser user); + + /// + /// Updates the specified in the backing store. + /// + /// The user to update. + /// + /// The that represents the asynchronous operation, containing the + /// of the operation. + /// + Task UpdateAsync(TUser user); + + /// + /// Returns a flag indicating whether the specified is valid for + /// the given and . + /// + /// The user to validate the token against. + /// The token provider used to generate the token. + /// The purpose the token should be generated for. + /// The token to validate + /// + /// The that represents the asynchronous operation, returning true if the + /// is valid, otherwise false. + /// + Task VerifyUserTokenAsync(TUser user, string tokenProvider, string purpose, + string token); + + /// + /// Adds the to the specified only if the user + /// does not already have a password. + /// + /// The user whose password should be set. + /// The password to set. + /// + /// The that represents the asynchronous operation, containing the + /// of the operation. + /// + Task AddPasswordAsync(TUser user, string password); + + + /// + /// Returns a flag indicating whether the given is valid for the + /// specified . + /// + /// The user whose password should be validated. + /// The password to validate + /// The that represents the asynchronous operation, containing true if + /// the specified matches the one store for the , + /// otherwise false. + Task CheckPasswordAsync(TUser user, string password); + + /// + /// Changes a user's password after confirming the specified is correct, + /// as an asynchronous operation. + /// + /// The user whose password should be set. + /// The current password to validate before changing. + /// The new password to set for the specified . + /// + /// The that represents the asynchronous operation, containing the + /// of the operation. + /// + Task ChangePasswordAsync(TUser user, string currentPassword, + string newPassword); + + /// + /// Used to validate a user's session + /// + /// + /// + /// + Task ValidateSessionIdAsync(string userId, string sessionId); + + /// + /// Creates the specified in the backing store with no password, + /// as an asynchronous operation. + /// + /// The user to create. + /// + /// The that represents the asynchronous operation, containing the + /// of the operation. + /// + Task CreateAsync(TUser user); + + /// + /// Helper method to generate a password for a user based on the current password validator + /// + /// + string GeneratePassword(); + + + /// + /// Generates an email confirmation token for the specified user. + /// + /// The user to generate an email confirmation token for. + /// + /// The that represents the asynchronous operation, an email confirmation token. + /// + Task GenerateEmailConfirmationTokenAsync(TUser user); + + /// + /// Finds and returns a user, if any, who has the specified user name. + /// + /// The user name to search for. + /// + /// The that represents the asynchronous operation, containing the user matching the specified if it exists. + /// + Task FindByNameAsync(string userName); + + /// + /// Increments the access failed count for the user as an asynchronous operation. + /// If the failed access account is greater than or equal to the configured maximum number of attempts, + /// the user will be locked out for the configured lockout time span. + /// + /// The user whose failed access count to increment. + /// The that represents the asynchronous operation, containing the of the operation. + Task AccessFailedAsync(TUser user); + + /// + /// Returns a flag indicating whether the specified has two factor authentication enabled or not, + /// as an asynchronous operation. + /// + /// The user whose two factor authentication enabled status should be retrieved. + /// + /// The that represents the asynchronous operation, true if the specified + /// has two factor authentication enabled, otherwise false. + /// + Task GetTwoFactorEnabledAsync(TUser user); + + /// + /// Gets a list of valid two factor token providers for the specified , + /// as an asynchronous operation. + /// + /// The user the whose two factor authentication providers will be returned. + /// + /// The that represents result of the asynchronous operation, a list of two + /// factor authentication providers for the specified user. + /// + Task> GetValidTwoFactorProvidersAsync(TUser user); + + /// + /// Verifies the specified two factor authentication against the . + /// + /// The user the token is supposed to be for. + /// The provider which will verify the token. + /// The token to verify. + /// + /// The that represents result of the asynchronous operation, true if the token is valid, + /// otherwise false. + /// + Task VerifyTwoFactorTokenAsync(TUser user, string tokenProvider, string token); + + /// + /// Adds an external Microsoft.AspNetCore.Identity.UserLoginInfo to the specified user. + /// + /// The user to add the login to. + /// The external Microsoft.AspNetCore.Identity.UserLoginInfo to add to the specified user. + /// The System.Threading.Tasks.Task that represents the asynchronous operation, containing the Microsoft.AspNetCore.Identity.IdentityResult of the operation. + Task AddLoginAsync(TUser user, UserLoginInfo login); + + /// + /// Attempts to remove the provided external login information from the specified user. and returns a flag indicating whether the removal succeed or not. + /// + /// The user to remove the login information from. + /// The login provide whose information should be removed. + /// The key given by the external login provider for the specified user. + /// The System.Threading.Tasks.Task that represents the asynchronous operation, containing the Microsoft.AspNetCore.Identity.IdentityResult of the operation. + Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey); + + Task ResetAccessFailedCountAsync(TUser user); + + Task GenerateTwoFactorTokenAsync(TUser user, string tokenProvider); + + /// + /// Gets the email address for the specified user. + /// + /// The user whose email should be returned. + /// The task object containing the results of the asynchronous operation, the email address for the specified user. + Task GetEmailAsync(TUser user); + + /// + /// Gets the telephone number, if any, for the specified user. + /// + /// The user whose telephone number should be retrieved. + /// The System.Threading.Tasks.Task that represents the asynchronous operation, containing the user's telephone number, if any. + /// + /// A user can only support a phone number if the BackOfficeUserStore is replaced with another that implements IUserPhoneNumberStore + /// + Task GetPhoneNumberAsync(TUser user); + + // TODO: These are raised from outside the signinmanager and usermanager in the auth and user controllers, + // let's see if there's a way to avoid that and only have these called within signinmanager and usermanager + // which means we can remove these from the interface (things like invite seems like they cannot be moved) + void RaiseForgotPasswordRequestedEvent(IPrincipal currentUser, int userId); + void RaiseForgotPasswordChangedSuccessEvent(IPrincipal currentUser, int userId); + SignOutAuditEventArgs RaiseLogoutSuccessEvent(IPrincipal currentUser, int userId); + UserInviteEventArgs RaiseSendingUserInvite(IPrincipal currentUser, UserInvite invite, IUser createdUser); + bool HasSendingUserInviteEventHandler { get; } + + } +} diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs index 04f715c7c0..ed45f24a96 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/CoreMappingProfiles.cs @@ -1,7 +1,7 @@ using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core.BackOffice; using Umbraco.Core.Builder; using Umbraco.Core.Mapping; +using Umbraco.Core.Security; using Umbraco.Web.Models.Mapping; namespace Umbraco.Core.Composing.CompositionExtensions diff --git a/src/Umbraco.Infrastructure/Security/SignOutAuditEventArgs.cs b/src/Umbraco.Infrastructure/Security/SignOutAuditEventArgs.cs index 961c2e6137..34bd9c9a42 100644 --- a/src/Umbraco.Infrastructure/Security/SignOutAuditEventArgs.cs +++ b/src/Umbraco.Infrastructure/Security/SignOutAuditEventArgs.cs @@ -1,4 +1,6 @@ -namespace Umbraco.Core.BackOffice +using Umbraco.Core.Security; + +namespace Umbraco.Core.BackOffice { /// diff --git a/src/Umbraco.Infrastructure/Security/UserInviteEventArgs.cs b/src/Umbraco.Infrastructure/Security/UserInviteEventArgs.cs index 4e980b7bb1..2aefb47c14 100644 --- a/src/Umbraco.Infrastructure/Security/UserInviteEventArgs.cs +++ b/src/Umbraco.Infrastructure/Security/UserInviteEventArgs.cs @@ -1,4 +1,5 @@ using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Core.BackOffice diff --git a/src/Umbraco.Tests.Integration/TestServerTest/TestAuthHandler.cs b/src/Umbraco.Tests.Integration/TestServerTest/TestAuthHandler.cs index b9acd9529c..ab5821c81c 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/TestAuthHandler.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/TestAuthHandler.cs @@ -4,9 +4,9 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.BackOffice; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Common.Security; diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UmbracoBackOfficeServiceCollectionExtensionsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UmbracoBackOfficeServiceCollectionExtensionsTests.cs index 26c3f7875c..b6a86344a2 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UmbracoBackOfficeServiceCollectionExtensionsTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice/UmbracoBackOfficeServiceCollectionExtensionsTests.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using Umbraco.Extensions; using Umbraco.Core.BackOffice; using Umbraco.Tests.Integration.Testing; +using Umbraco.Core.Security; namespace Umbraco.Tests.Integration.Umbraco.Web.BackOffice { diff --git a/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs b/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs index 78d5d5554c..365dca780c 100644 --- a/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs +++ b/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs @@ -10,10 +10,10 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Moq; using Umbraco.Core; -using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; +using Umbraco.Core.Security; using Umbraco.Tests.Common.Builders; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.BackOffice.Routing; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/BackOfficeClaimsPrincipalFactoryTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/BackOfficeClaimsPrincipalFactoryTests.cs index 5291c1b12e..9d8edbc75e 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/BackOfficeClaimsPrincipalFactoryTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/BackOfficeClaimsPrincipalFactoryTests.cs @@ -10,6 +10,7 @@ using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Extensions; namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice @@ -98,7 +99,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice const string expectedClaimType = ClaimTypes.Role; const string expectedClaimValue = "b87309fb-4caf-48dc-b45a-2b752d051508"; - _testUser.Roles.Add(new global::Umbraco.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}); @@ -115,7 +116,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice const string expectedClaimType = "custom"; const string expectedClaimValue = "val"; - _testUser.Claims.Add(new global::Umbraco.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.UnitTests/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentityTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentityTests.cs index 9e9d29a123..8dcaafafcb 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentityTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/BackOffice/UmbracoBackOfficeIdentityTests.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Security.Claims; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/ClaimsPrincipalExtensionsTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/ClaimsPrincipalExtensionsTests.cs index a078456f8f..30706b1b67 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/ClaimsPrincipalExtensionsTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/ClaimsPrincipalExtensionsTests.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Security.Claims; using Umbraco.Extensions; using Umbraco.Core; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Tests.UnitTests.Umbraco.Core.Extensions { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/UsersControllerUnitTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/UsersControllerUnitTests.cs index b04a5ff158..6ecda57cc6 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/UsersControllerUnitTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/UsersControllerUnitTests.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Identity; using Moq; using NUnit.Framework; using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; using Umbraco.Tests.UnitTests.AutoFixture; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.Common.Exceptions; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Security/BackOfficeAntiforgeryTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Security/BackOfficeAntiforgeryTests.cs index d93bc01b4e..ccebe17b09 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Security/BackOfficeAntiforgeryTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Security/BackOfficeAntiforgeryTests.cs @@ -1,19 +1,15 @@ -using Microsoft.AspNetCore.Antiforgery; +using System; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; -using Moq; using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Text; -using System.Threading.Tasks; using Umbraco.Core; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; using Umbraco.Web.BackOffice.Security; namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Security @@ -25,8 +21,16 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Security { var httpContext = new DefaultHttpContext() { - User = new ClaimsPrincipal(new UmbracoBackOfficeIdentity(-1, "test", "test", Enumerable.Empty(), Enumerable.Empty(), "en-US", - Guid.NewGuid().ToString(), Enumerable.Empty(), Enumerable.Empty())) + User = new ClaimsPrincipal(new UmbracoBackOfficeIdentity( + -1, + "test", + "test", + Enumerable.Empty(), + Enumerable.Empty(), + "en-US", + Guid.NewGuid().ToString(), + Enumerable.Empty(), + Enumerable.Empty())) }; httpContext.Request.IsHttps = true; return httpContext; diff --git a/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs b/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs index 66965ca632..c44844fd66 100644 --- a/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs +++ b/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs @@ -6,10 +6,10 @@ 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.Configuration.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Tests.Common.Builders; using Umbraco.Web.Security; diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs index 48ffdbcdec..3673bdf333 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs @@ -1,10 +1,10 @@ -using System; +using System; using System.Threading.Tasks; using Microsoft.Owin; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Infrastructure; using Owin; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Tests.TestHelpers.ControllerTesting { diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 23f7e09f5d..f993ee5b6a 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -6,7 +6,6 @@ using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; using Moq; -using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.PublishedContent; diff --git a/src/Umbraco.Web.BackOffice/Extensions/IdentityBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/IdentityBuilderExtensions.cs index ddf46a24a7..e6385e6bf9 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/IdentityBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/IdentityBuilderExtensions.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Extensions { diff --git a/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs index 9cfaae6980..a770a01e4d 100644 --- a/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/CheckIfUserTicketDataIsStaleAttribute.cs @@ -7,12 +7,12 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.BackOffice; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Extensions; using Umbraco.Web.BackOffice.Security; diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficePasswordHasher.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficePasswordHasher.cs index 6c61e7bb35..65f1a7f5bc 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficePasswordHasher.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficePasswordHasher.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Identity; -using Umbraco.Core.BackOffice; using Umbraco.Core.Security; using Umbraco.Core; using Umbraco.Core.Models.Membership; diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeSecureDataFormat.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeSecureDataFormat.cs index 91b982b5f6..377801a0b7 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeSecureDataFormat.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeSecureDataFormat.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Authentication; using System; using System.Security.Claims; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Web.BackOffice.Security { diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeSecurityStampValidator.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeSecurityStampValidator.cs index f12b6279bb..abd0af1353 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeSecurityStampValidator.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeSecurityStampValidator.cs @@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; using Umbraco.Web.Common.Security; namespace Umbraco.Web.BackOffice.Security diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs index e17067daa0..6d1c348d7f 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs @@ -9,7 +9,6 @@ using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Umbraco.Core; -using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Security; diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeUserManager.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeUserManager.cs index 2906d9d87a..cc9b9410a6 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeUserManager.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeUserManager.cs @@ -65,6 +65,7 @@ namespace Umbraco.Web.Common.Security IpResolver = ipResolver ?? throw new ArgumentNullException(nameof(ipResolver)); _httpContextAccessor = httpContextAccessor; PasswordConfiguration = passwordConfiguration.Value ?? throw new ArgumentNullException(nameof(passwordConfiguration)); + } // We don't support an IUserClaimStore and don't need to (at least currently) diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeUserManagerAuditer.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeUserManagerAuditer.cs index 019eed7e39..5f0757ea9c 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeUserManagerAuditer.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeUserManagerAuditer.cs @@ -6,6 +6,7 @@ using Umbraco.Core.BackOffice; using Umbraco.Core.Compose; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; using Umbraco.Core.Services; namespace Umbraco.Web.Common.Security diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs index 590edf397a..9f90395ff3 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs @@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.BackOffice; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; diff --git a/src/Umbraco.Web.BackOffice/Security/ExternalSignInAutoLinkOptions.cs b/src/Umbraco.Web.BackOffice/Security/ExternalSignInAutoLinkOptions.cs index 8d9f57945b..8636d9e62d 100644 --- a/src/Umbraco.Web.BackOffice/Security/ExternalSignInAutoLinkOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ExternalSignInAutoLinkOptions.cs @@ -1,8 +1,8 @@ using Microsoft.AspNetCore.Identity; using System; using System.Runtime.Serialization; -using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Security; using SecurityConstants = Umbraco.Core.Constants.Security; namespace Umbraco.Web.BackOffice.Security diff --git a/src/Umbraco.Web.BackOffice/Security/IBackOfficeSignInManager.cs b/src/Umbraco.Web.BackOffice/Security/IBackOfficeSignInManager.cs index ce87484b2c..669ca21239 100644 --- a/src/Umbraco.Web.BackOffice/Security/IBackOfficeSignInManager.cs +++ b/src/Umbraco.Web.BackOffice/Security/IBackOfficeSignInManager.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Identity; using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Web.Common.Security { diff --git a/src/Umbraco.Web.Common/Extensions/HttpContextExtensions.cs b/src/Umbraco.Web.Common/Extensions/HttpContextExtensions.cs index 15d3d04c0b..f484ddac18 100644 --- a/src/Umbraco.Web.Common/Extensions/HttpContextExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/HttpContextExtensions.cs @@ -5,7 +5,7 @@ using System.Security.Claims; using System.Security.Principal; using System.Text; using Microsoft.AspNetCore.Http.Features; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Extensions { diff --git a/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs b/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs index 82c9cb8496..8071af2f5d 100644 --- a/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs +++ b/src/Umbraco.Web/Security/ActiveDirectoryBackOfficeUserPasswordChecker.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.DirectoryServices.AccountManagement; using System.Threading.Tasks; using Microsoft.Extensions.Options; @@ -9,6 +9,7 @@ using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.Security { // TODO: This relies on an assembly that is not .NET Standard (at least not at the time of implementation) :( + // TODO: This could be ported now, see https://stackoverflow.com/questions/37330705/working-with-directoryservices-in-asp-net-core public class ActiveDirectoryBackOfficeUserPasswordChecker : IBackOfficeUserPasswordChecker { private readonly IOptions _activeDirectorySettings; diff --git a/src/Umbraco.Web/Security/AuthenticationExtensions.cs b/src/Umbraco.Web/Security/AuthenticationExtensions.cs index de5abf8a6b..aa0cd6aca2 100644 --- a/src/Umbraco.Web/Security/AuthenticationExtensions.cs +++ b/src/Umbraco.Web/Security/AuthenticationExtensions.cs @@ -12,8 +12,8 @@ using Microsoft.Owin; using Microsoft.Owin.Security; using Newtonsoft.Json; using Umbraco.Core; -using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Security; using Umbraco.Extensions; using Umbraco.Web.Composing; using Constants = Umbraco.Core.Constants; diff --git a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs index e5ba931b0b..010c2d4d33 100644 --- a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs @@ -10,6 +10,7 @@ using Microsoft.Owin.Security; using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Security; namespace Umbraco.Web.Security { diff --git a/src/Umbraco.Web/Security/FixWindowsAuthMiddlware.cs b/src/Umbraco.Web/Security/FixWindowsAuthMiddlware.cs index 9e26964091..3338344e73 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.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Web.Security { diff --git a/src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs b/src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs index 2fae308eb0..7bd67e608a 100644 --- a/src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs +++ b/src/Umbraco.Web/Security/IBackOfficeUserPasswordChecker.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Umbraco.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Web.Security { diff --git a/src/Umbraco.Web/Security/OwinDataProtectorTokenProvider.cs b/src/Umbraco.Web/Security/OwinDataProtectorTokenProvider.cs index 72e12b8621..429014dea8 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.Core.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Web.Security { diff --git a/src/Umbraco.Web/Security/UmbracoSecureDataFormat.cs b/src/Umbraco.Web/Security/UmbracoSecureDataFormat.cs index 73c1c3fd55..d1b0c54279 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.BackOffice; +using Umbraco.Core.Security; namespace Umbraco.Web.Security {