diff --git a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs index 1668b6776d..946810ffc9 100644 --- a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs @@ -171,9 +171,11 @@ namespace Umbraco.Web.Security.Identity app.Use(typeof(CookieAuthenticationMiddleware), app, options); app.UseStageMarker(PipelineStage.Authenticate); - //Then our custom middleware + //Then our custom middlewares app.Use(typeof(ForceRenewalCookieAuthenticationMiddleware), app, options); app.UseStageMarker(PipelineStage.Authenticate); + app.Use(typeof(FixWindowsAuthMiddlware)); + app.UseStageMarker(PipelineStage.Authenticate); return app; } diff --git a/src/Umbraco.Web/Security/Identity/FixWindowsAuthMiddlware.cs b/src/Umbraco.Web/Security/Identity/FixWindowsAuthMiddlware.cs new file mode 100644 index 0000000000..911a304019 --- /dev/null +++ b/src/Umbraco.Web/Security/Identity/FixWindowsAuthMiddlware.cs @@ -0,0 +1,51 @@ +using System.Linq; +using System.Security.Claims; +using System.Security.Principal; +using System.Threading.Tasks; +using Microsoft.Owin; +using Umbraco.Core; +using Umbraco.Core.Security; + +namespace Umbraco.Web.Security.Identity +{ + /// + /// This is used to inspect the request to see if 2 x identities are assigned: A windows one and a back office one. + /// When this is the case, it means that auth has executed for Windows & auth has executed for our back office cookie + /// handler and now two identities have been assigned. Unfortunately, at some stage in the pipeline - I'm pretty sure + /// it's the Role Provider Module - it again changes the user's Principal to a RolePrincipal and discards the second + /// Identity which is the Back office identity thus preventing a user from accessing the back office... it's very annoying. + /// + /// To fix this, we re-set the user Principal to only have a single identity: the back office one, since we know this is + /// for a back office request. + /// + internal class FixWindowsAuthMiddlware : OwinMiddleware + { + public FixWindowsAuthMiddlware(OwinMiddleware next) : base(next) + { + } + + public override async Task Invoke(IOwinContext context) + { + if (context.Request.Uri.IsClientSideRequest() == false) + { + var claimsPrincipal = context.Request.User as ClaimsPrincipal; + if (claimsPrincipal != null + && claimsPrincipal.Identities.Count() > 1 + && claimsPrincipal.Identities.Any(x => x is WindowsIdentity) + && claimsPrincipal.Identities.Any(x => x is UmbracoBackOfficeIdentity)) + { + var backOfficeIdentity = claimsPrincipal.Identities.First(x => x is UmbracoBackOfficeIdentity); + if (backOfficeIdentity.IsAuthenticated) + { + context.Request.User = new ClaimsPrincipal(backOfficeIdentity); + } + } + } + + if (Next != null) + { + await Next.Invoke(context); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 6be3318fb4..1edf654af6 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -310,6 +310,7 @@ +