From 6c7316afcddf18eaa5b44c21462e439ad8ccc7ec Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Fri, 19 Feb 2021 11:45:58 +0100 Subject: [PATCH] Move preview authorization middleware to fix preview --- .../UmbracoBuilderExtensions.cs | 1 - .../BackOfficeApplicationBuilderExtensions.cs | 3 -- .../UmbracoBuilderExtensions.cs | 1 + .../ApplicationBuilderExtensions.cs | 1 + .../PreviewAuthenticationMiddleware.cs | 52 ++++++++++++------- 5 files changed, 36 insertions(+), 22 deletions(-) rename src/{Umbraco.Web.BackOffice => Umbraco.Web.Common}/Middleware/PreviewAuthenticationMiddleware.cs (53%) diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs index 4baf6a29f5..a14a2fbbbb 100644 --- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilderExtensions.cs @@ -75,7 +75,6 @@ namespace Umbraco.Extensions builder.Services.ConfigureOptions(); - builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); diff --git a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs index d63deda88a..35f41e0af7 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs @@ -44,9 +44,6 @@ namespace Umbraco.Extensions public static IApplicationBuilder UseUmbracoPreview(this IApplicationBuilder app) { - // TODO: I'm unsure this middleware will execute before the endpoint, we'll have to see - app.UseMiddleware(); - app.UseEndpoints(endpoints => { PreviewRoutes previewRoutes = app.ApplicationServices.GetRequiredService(); diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs index f941a4a0f7..d703518b1e 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs @@ -272,6 +272,7 @@ namespace Umbraco.Extensions builder.Services.AddUnique(); builder.Services.AddUnique(); + builder.Services.AddUnique(); builder.Services.AddUnique(); builder.Services.AddUnique(); diff --git a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs index 75a5f95f21..ba7ab73131 100644 --- a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs @@ -125,6 +125,7 @@ namespace Umbraco.Extensions } else { + app.UseMiddleware(); app.UseMiddleware(); app.UseMiddleware(); } diff --git a/src/Umbraco.Web.BackOffice/Middleware/PreviewAuthenticationMiddleware.cs b/src/Umbraco.Web.Common/Middleware/PreviewAuthenticationMiddleware.cs similarity index 53% rename from src/Umbraco.Web.BackOffice/Middleware/PreviewAuthenticationMiddleware.cs rename to src/Umbraco.Web.Common/Middleware/PreviewAuthenticationMiddleware.cs index b03769d28b..50338f70e3 100644 --- a/src/Umbraco.Web.BackOffice/Middleware/PreviewAuthenticationMiddleware.cs +++ b/src/Umbraco.Web.Common/Middleware/PreviewAuthenticationMiddleware.cs @@ -3,35 +3,47 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Extensions; -using Constants = Umbraco.Cms.Core.Constants; -namespace Umbraco.Cms.Web.BackOffice.Middleware +namespace Umbraco.Cms.Web.Common.Middleware { /// /// Ensures that preview pages (front-end routed) are authenticated with the back office identity appended to the principal alongside any default authentication that takes place /// public class PreviewAuthenticationMiddleware : IMiddleware { + private readonly ILogger _logger; + + public PreviewAuthenticationMiddleware(ILogger logger) => _logger = logger; + /// public async Task InvokeAsync(HttpContext context, RequestDelegate next) { var request = context.Request; - if (!request.IsClientSideRequest()) + + // do not process if client-side request + if (request.IsClientSideRequest()) + { + await next(context); + return; + } + + try { var isPreview = request.HasPreviewCookie() - && context.User != null - && !request.IsBackOfficeRequest(); + && context.User != null + && !request.IsBackOfficeRequest(); if (isPreview) { var cookieOptions = context.RequestServices.GetRequiredService>() - .Get(Constants.Security.BackOfficeAuthenticationType); + .Get(Core.Constants.Security.BackOfficeAuthenticationType); if (cookieOptions == null) { - throw new InvalidOperationException("No cookie options found with name " + Constants.Security.BackOfficeAuthenticationType); + throw new InvalidOperationException("No cookie options found with name " + Core.Constants.Security.BackOfficeAuthenticationType); } // If we've gotten this far it means a preview cookie has been set and a front-end umbraco document request is executing. @@ -40,23 +52,27 @@ namespace Umbraco.Cms.Web.BackOffice.Middleware if (request.Cookies.TryGetValue(cookieOptions.Cookie.Name, out var cookie)) { var unprotected = cookieOptions.TicketDataFormat.Unprotect(cookie); - if (unprotected != null) + var backOfficeIdentity = unprotected?.Principal.GetUmbracoIdentity(); + if (backOfficeIdentity != null) { - var backOfficeIdentity = unprotected.Principal.GetUmbracoIdentity(); - if (backOfficeIdentity != null) - { - // Ok, we've got a real ticket, now we can add this ticket's identity to the current - // Principal, this means we'll have 2 identities assigned to the principal which we can - // use to authorize the preview and allow for a back office User. - context.User.AddIdentity(backOfficeIdentity); - } + // Ok, we've got a real ticket, now we can add this ticket's identity to the current + // Principal, this means we'll have 2 identities assigned to the principal which we can + // use to authorize the preview and allow for a back office User. + context.User.AddIdentity(backOfficeIdentity); } } } } - - await next(context); + catch (Exception ex) + { + // log any errors and continue the request without preview + _logger.LogError($"Unable to perform preview authentication: {ex.Message}"); + } + finally + { + await next(context); + } } } }