diff --git a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityRole.cs b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityRole.cs new file mode 100644 index 0000000000..9fb4c51f52 --- /dev/null +++ b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityRole.cs @@ -0,0 +1,22 @@ +using Microsoft.AspNet.Identity; + +namespace Umbraco.Core.Models.Identity +{ + public class BackOfficeIdentityRole : IRole + { + public BackOfficeIdentityRole(string id) + { + Id = id; + } + + /// + /// Id of the role + /// + public string Id { get; private set; } + + /// + /// Name of the role + /// + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Security/BackOfficeRoleManager.cs b/src/Umbraco.Core/Security/BackOfficeRoleManager.cs new file mode 100644 index 0000000000..c49a6b943b --- /dev/null +++ b/src/Umbraco.Core/Security/BackOfficeRoleManager.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.Owin; +using Umbraco.Core.Models.Identity; + +namespace Umbraco.Core.Security +{ + public class BackOfficeRoleManager : RoleManager + { + /// + /// Constructor + /// + /// The IRoleStore is responsible for commiting changes via the UpdateAsync/CreateAsync methods + public BackOfficeRoleManager(IRoleStore store) : base(store) + { + } + + public static BackOfficeRoleManager Create( + IdentityFactoryOptions options) + { + //TODO: Set this up! + + var manager = new BackOfficeRoleManager(new BackOfficeRoleStore()); + + return manager; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Security/BackOfficeRoleStore.cs b/src/Umbraco.Core/Security/BackOfficeRoleStore.cs new file mode 100644 index 0000000000..603f2e1ed2 --- /dev/null +++ b/src/Umbraco.Core/Security/BackOfficeRoleStore.cs @@ -0,0 +1,67 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; +using Umbraco.Core.Models.Identity; + +namespace Umbraco.Core.Security +{ + public class BackOfficeRoleStore : DisposableObject, IRoleStore + { + /// + /// Handles the disposal of resources. Derived from abstract class which handles common required locking logic. + /// + protected override void DisposeResources() + { + } + + /// + /// Create a new role + /// + /// + /// + public Task CreateAsync(BackOfficeIdentityRole role) + { + throw new NotImplementedException(); + } + + /// + /// Update a role + /// + /// + /// + public Task UpdateAsync(BackOfficeIdentityRole role) + { + throw new NotImplementedException(); + } + + /// + /// Delete a role + /// + /// + /// + public Task DeleteAsync(BackOfficeIdentityRole role) + { + throw new NotImplementedException(); + } + + /// + /// Find a role by id + /// + /// + /// + public Task FindByIdAsync(string roleId) + { + throw new NotImplementedException(); + } + + /// + /// Find a role by name + /// + /// + /// + public Task FindByNameAsync(string roleName) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Security/BackOfficeUserManager.cs b/src/Umbraco.Core/Security/BackOfficeUserManager.cs index 9634b17c73..b65b9dfaa1 100644 --- a/src/Umbraco.Core/Security/BackOfficeUserManager.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserManager.cs @@ -12,33 +12,6 @@ using Umbraco.Core.Services; namespace Umbraco.Core.Security { - /// - /// A custom password hasher that conforms to the current password hashing done in Umbraco - /// - internal class MembershipPasswordHasher : IPasswordHasher - { - private readonly MembershipProviderBase _provider; - - public MembershipPasswordHasher(MembershipProviderBase provider) - { - _provider = provider; - } - - public string HashPassword(string password) - { - return _provider.HashPasswordForStorage(password); - } - - public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword) - { - return _provider.VerifyPassword(providedPassword, hashedPassword) - ? PasswordVerificationResult.Success - : PasswordVerificationResult.Failed; - } - - - } - /// /// Back office user manager /// @@ -51,6 +24,12 @@ namespace Umbraco.Core.Security #region What we support currently + //NOTE: Not sure if we really want/need to ever support this + public override bool SupportsUserClaim + { + get { return false; } + } + //TODO: Support this public override bool SupportsUserRole { @@ -75,11 +54,13 @@ namespace Umbraco.Core.Security get { return false; } } + //TODO: Support this public override bool SupportsUserTwoFactor { get { return false; } } + //TODO: Support this public override bool SupportsUserPhoneNumber { get { return false; } @@ -127,7 +108,7 @@ namespace Umbraco.Core.Security } //custom identity factory for creating the identity object for which we auth against in the back office - manager.ClaimsIdentityFactory = new BackOfficeClaimsIdentityFactory(); + manager.ClaimsIdentityFactory = new BackOfficeClaimsIdentityFactory(); //NOTE: Not implementing these currently diff --git a/src/Umbraco.Core/Security/BackOfficeUserStore.cs b/src/Umbraco.Core/Security/BackOfficeUserStore.cs index 83676b9c1f..6dd4aadc3e 100644 --- a/src/Umbraco.Core/Security/BackOfficeUserStore.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserStore.cs @@ -11,7 +11,23 @@ using Umbraco.Core.Services; namespace Umbraco.Core.Security { - public class BackOfficeUserStore : DisposableObject, IUserStore, IUserPasswordStore, IUserEmailStore, IUserLoginStore + public class BackOfficeUserStore : DisposableObject, + IUserStore, + IUserPasswordStore, + IUserEmailStore, + IUserLoginStore + + //IUserRoleStore, + + //TODO: This will require additional columns/tables + //IUserLockoutStore + + //TODO: Implement this - might need to add a new column for this + // http://stackoverflow.com/questions/19487322/what-is-asp-net-identitys-iusersecuritystampstoretuser-interface + //IUserSecurityStampStore + + //TODO: To do this we need to implement IQueryable - seems pretty overkill? + //IQueryableUserStore { private readonly IUserService _userService; private readonly IExternalLoginService _externalLoginService; diff --git a/src/Umbraco.Core/Security/UmbracoMembersMembershipProviderBase.cs b/src/Umbraco.Core/Security/IUmbracoMemberTypeMembershipProvider.cs similarity index 100% rename from src/Umbraco.Core/Security/UmbracoMembersMembershipProviderBase.cs rename to src/Umbraco.Core/Security/IUmbracoMemberTypeMembershipProvider.cs diff --git a/src/Umbraco.Core/Security/MembershipPasswordHasher.cs b/src/Umbraco.Core/Security/MembershipPasswordHasher.cs new file mode 100644 index 0000000000..56daa3efdd --- /dev/null +++ b/src/Umbraco.Core/Security/MembershipPasswordHasher.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNet.Identity; + +namespace Umbraco.Core.Security +{ + /// + /// A custom password hasher that conforms to the current password hashing done in Umbraco + /// + internal class MembershipPasswordHasher : IPasswordHasher + { + private readonly MembershipProviderBase _provider; + + public MembershipPasswordHasher(MembershipProviderBase provider) + { + _provider = provider; + } + + public string HashPassword(string password) + { + return _provider.HashPasswordForStorage(password); + } + + public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword) + { + return _provider.VerifyPassword(providedPassword, hashedPassword) + ? PasswordVerificationResult.Success + : PasswordVerificationResult.Failed; + } + + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index 5a77956931..aa8250cf59 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using Umbraco.Core.Models.Membership; namespace Umbraco.Core.Services diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 85fe6d55bc..0c2c0bee73 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -345,6 +345,7 @@ + @@ -419,8 +420,11 @@ + + + @@ -1144,7 +1148,7 @@ - + diff --git a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs index c1a6ed26a8..0e8712ed07 100644 --- a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs @@ -37,6 +37,9 @@ namespace Umbraco.Web.Security.Identity appContext.Services.UserService, appContext.Services.ExternalLoginService, userMembershipProvider)); + + //Configure Umbraco role manager to be created per request + app.CreatePerOwinContext((options, owinContext) => BackOfficeRoleManager.Create(options)); } /// @@ -70,14 +73,16 @@ namespace Umbraco.Web.Security.Identity return app; } + /// + /// Ensures that the cookie middleware for validating external logins is assigned to the pipeline with the correct + /// Umbraco back office configuration + /// + /// + /// public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app) { if (app == null) throw new ArgumentNullException("app"); - //TODO: Figure out why this isn't working and is only working with the default one, must be a reference somewhere - - //app.UseExternalSignInCookie("UmbracoExternalCookie"); - app.SetDefaultSignInAsAuthenticationType("UmbracoExternalCookie"); app.UseCookieAuthentication(new CookieAuthenticationOptions { @@ -93,11 +98,6 @@ namespace Umbraco.Web.Security.Identity CookieDomain = UmbracoConfig.For.UmbracoSettings().Security.AuthCookieDomain }); - - //NOTE: This works, but this is just the default implementation which we don't want because other devs - //might want to use this... right? - //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); - return app; }