Save and Preview - Public Access - Mandatory Login

When I use Save and Preview in Umbraco and the page (or its parent) has a Public Access configuration, I can only preview the page if I’m already logged in as a Member on my website.
If I’m not logged in as a Member, the preview just shows the login page instead of the actual preview.

However, it’s impossible to log in as a Member in this situation, because the preview runs inside an iframe without sandbox="allow-forms", so form submissions (like the login form) are blocked by the browser.

Is this the expected behavior?
This basically forces Umbraco users to also have a Member account just to preview these pages, which doesn’t seem ideal.

I believe it’s been like this since forever.

There are packages that allow you to impersonate members which could allow your editors to view the page as a fake member.
I think it’s also possible to just make your own, impersonation logic if you don’t want to bring in 3. party plugins.

You could also look into various ways to render the content in the backoffice like views for Block elements.
I think there’s also packages that allow for direct preview inside the backoffice that might work for you.

There’s probably other options as well, but these are the ones I can think of right now.

Yep, fake member solve the problem, thank you.

public class PreviewMemberNotificationHandler :
    INotificationAsyncHandler<UserLoginSuccessNotification>,
    INotificationAsyncHandler<UserLogoutSuccessNotification>
{
    private readonly IMemberSignInManager _memberSignInManager;
    private readonly UserManager<MemberIdentityUser> _memberUserManager;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public PreviewMemberNotificationHandler(
        IMemberSignInManager memberSignInManager,
        UserManager<MemberIdentityUser> memberUserManager,
        IHttpContextAccessor httpContextAccessor)
    {
        _memberSignInManager = memberSignInManager;
        _memberUserManager = memberUserManager;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task HandleAsync(UserLoginSuccessNotification notification, CancellationToken cancellationToken)
    {
        var member = await _memberUserManager.FindByEmailAsync("[email protected]");
        if (member != null)
        {
            await _memberSignInManager.SignInAsync(member, isPersistent: false);
        }
    }

    public async Task HandleAsync(UserLogoutSuccessNotification notification, CancellationToken cancellationToken)
    {
        await _memberSignInManager.SignOutAsync();
    }
   
}
1 Like