2020-12-08 16:33:50 +11:00
using Microsoft.AspNetCore.Authentication.Cookies ;
2020-08-07 00:48:32 +10:00
using Microsoft.AspNetCore.Http ;
using Microsoft.Extensions.DependencyInjection ;
using Microsoft.Extensions.Options ;
using System ;
using System.Threading.Tasks ;
using Umbraco.Core ;
using Umbraco.Core.Configuration ;
2020-08-21 15:27:06 +01:00
using Umbraco.Core.Configuration.Models ;
2020-08-07 00:48:32 +10:00
using Umbraco.Core.Hosting ;
using Umbraco.Extensions ;
2020-10-23 14:18:53 +11:00
namespace Umbraco.Web.BackOffice.Middleware
2020-08-07 00:48:32 +10:00
{
/// <summary>
/// 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
/// </summary>
public class PreviewAuthenticationMiddleware : IMiddleware
{
2020-08-21 15:27:06 +01:00
private readonly GlobalSettings _globalSettings ;
2020-08-07 00:48:32 +10:00
private readonly IHostingEnvironment _hostingEnvironment ;
public PreviewAuthenticationMiddleware (
2020-08-23 23:36:48 +02:00
IOptions < GlobalSettings > globalSettings ,
2020-08-07 00:48:32 +10:00
IHostingEnvironment hostingEnvironment )
{
2020-08-21 15:27:06 +01:00
_globalSettings = globalSettings . Value ;
2020-08-07 00:48:32 +10:00
_hostingEnvironment = hostingEnvironment ;
}
public async Task InvokeAsync ( HttpContext context , RequestDelegate next )
{
var request = context . Request ;
if ( ! request . IsClientSideRequest ( ) )
{
var isPreview = request . HasPreviewCookie ( )
& & context . User ! = null
& & ! request . IsBackOfficeRequest ( _globalSettings , _hostingEnvironment ) ;
if ( isPreview )
{
var cookieOptions = context . RequestServices . GetRequiredService < IOptionsSnapshot < CookieAuthenticationOptions > > ( )
. Get ( Constants . Security . BackOfficeAuthenticationType ) ;
if ( cookieOptions = = null )
throw new InvalidOperationException ( "No cookie options found with name " + Constants . Security . BackOfficeAuthenticationType ) ;
2020-12-08 16:33:50 +11:00
// If we've gotten this far it means a preview cookie has been set and a front-end umbraco document request is executing.
2020-08-07 00:48:32 +10:00
// In this case, authentication will not have occurred for an Umbraco back office User, however we need to perform the authentication
// for the user here so that the preview capability can be authorized otherwise only the non-preview page will be rendered.
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 )
2020-12-08 16:33:50 +11:00
// Ok, we've got a real ticket, now we can add this ticket's identity to the current
2020-08-07 00:48:32 +10:00
// 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 ) ;
}
}
}