diff --git a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs index 31c56ba013..1523cf9040 100644 --- a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs +++ b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs @@ -12,7 +12,7 @@ namespace Umbraco.Core.Models.Identity public class BackOfficeIdentityUser : IdentityUser, IdentityUserClaim> { - public async Task GenerateUserIdentityAsync(BackOfficeUserManager manager) + public virtual async Task GenerateUserIdentityAsync(BackOfficeUserManager manager) { // NOTE the authenticationType must match the umbraco one // defined in CookieAuthenticationOptions.AuthenticationType diff --git a/src/Umbraco.Core/Models/Identity/IdentityUser.cs b/src/Umbraco.Core/Models/Identity/IdentityUser.cs index 09306bb1f0..cba4fc514a 100644 --- a/src/Umbraco.Core/Models/Identity/IdentityUser.cs +++ b/src/Umbraco.Core/Models/Identity/IdentityUser.cs @@ -18,6 +18,18 @@ namespace Umbraco.Core.Models.Identity where TRole : IdentityUserRole where TClaim : IdentityUserClaim { + + /// + /// Constructor + /// + /// + public IdentityUser() + { + this.Claims = new List(); + this.Roles = new List(); + this.Logins = new List(); + } + /// /// Email /// @@ -108,15 +120,6 @@ namespace Umbraco.Core.Models.Identity /// public virtual string UserName { get; set; } - /// - /// Constructor - /// - /// - public IdentityUser() - { - this.Claims = new List(); - this.Roles = new List(); - this.Logins = new List(); - } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Security/BackOfficeUserManager.cs b/src/Umbraco.Core/Security/BackOfficeUserManager.cs index b410f34107..def46b7556 100644 --- a/src/Umbraco.Core/Security/BackOfficeUserManager.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserManager.cs @@ -13,47 +13,14 @@ using Umbraco.Core.Services; namespace Umbraco.Core.Security { /// - /// Back office user manager + /// Default back office user manager /// - public class BackOfficeUserManager : UserManager + public class BackOfficeUserManager : BackOfficeUserManager { public BackOfficeUserManager(IUserStore store) : base(store) { } - - #region What we support do not 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 SupportsQueryableUsers - { - get { return false; } - } - - //TODO: Support this - public override bool SupportsUserLockout - { - get { return false; } - } - - //TODO: Support this - public override bool SupportsUserTwoFactor - { - get { return false; } - } - - //TODO: Support this - public override bool SupportsUserPhoneNumber - { - get { return false; } - } - #endregion /// /// Creates a BackOfficeUserManager instance with all default options and the default BackOfficeUserManager @@ -155,10 +122,51 @@ namespace Umbraco.Core.Security return manager; } + } - protected override void Dispose(bool disposing) + /// + /// Generic Back office user manager + /// + public class BackOfficeUserManager : UserManager + where T : BackOfficeIdentityUser + { + public BackOfficeUserManager(IUserStore store) + : base(store) { - base.Dispose(disposing); } + + #region What we support do not 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 SupportsQueryableUsers + { + get { return false; } + } + + //TODO: Support this + public override bool SupportsUserLockout + { + get { return false; } + } + + //TODO: Support this + public override bool SupportsUserTwoFactor + { + get { return false; } + } + + //TODO: Support this + public override bool SupportsUserPhoneNumber + { + get { return false; } + } + #endregion + } } diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 3a6f91eb2c..40ca7d428a 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -472,6 +472,12 @@ namespace Umbraco.Web.Editors var user = await UserManager.FindAsync(loginInfo.Login); if (user != null) { + //TODO: It might be worth keeping some of the claims associated with the ExternalLoginInfo, in which case we + // wouldn't necessarily sign the user in here with the standard login, instead we'd update the + // UseUmbracoBackOfficeExternalCookieAuthentication extension method to have the correct provider and claims factory, + // ticket format, etc.. to create our back office user including the claims assigned and in this method we'd just ensure + // that the ticket is created and stored and that the user is logged in. + //sign in await SignInAsync(user, isPersistent: false); } diff --git a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs index bd8e47b6b3..c1cff6a5aa 100644 --- a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using System.Web; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; @@ -31,6 +32,9 @@ namespace Umbraco.Web.Security.Identity ApplicationContext appContext, MembershipProviderBase userMembershipProvider) { + if (appContext == null) throw new ArgumentNullException("appContext"); + if (userMembershipProvider == null) throw new ArgumentNullException("userMembershipProvider"); + //Don't proceed if the app is not ready if (appContext.IsConfigured == false || appContext.DatabaseContext == null @@ -57,6 +61,10 @@ namespace Umbraco.Web.Security.Identity MembershipProviderBase userMembershipProvider, BackOfficeUserStore customUserStore) { + if (appContext == null) throw new ArgumentNullException("appContext"); + if (userMembershipProvider == null) throw new ArgumentNullException("userMembershipProvider"); + if (customUserStore == null) throw new ArgumentNullException("customUserStore"); + //Don't proceed if the app is not ready if (appContext.IsConfigured == false || appContext.DatabaseContext == null @@ -70,6 +78,30 @@ namespace Umbraco.Web.Security.Identity userMembershipProvider)); } + /// + /// Configure a custom BackOfficeUserManager for Umbraco + /// + /// + /// + /// + public static void ConfigureUserManagerForUmbracoBackOffice(this IAppBuilder app, + ApplicationContext appContext, + Func, IOwinContext, TManager> userManager) + where TManager : BackOfficeUserManager + where TUser : BackOfficeIdentityUser + { + if (appContext == null) throw new ArgumentNullException("appContext"); + if (userManager == null) throw new ArgumentNullException("userManager"); + + //Don't proceed if the app is not ready + if (appContext.IsConfigured == false + || appContext.DatabaseContext == null + || appContext.DatabaseContext.IsDatabaseConfigured == false) return; + + //Configure Umbraco user manager to be created per request + app.CreatePerOwinContext(userManager); + } + /// /// Ensures that the UmbracoBackOfficeAuthenticationMiddleware is assigned to the pipeline ///