diff --git a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs index b8db09f9b7..d83123edc6 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs @@ -64,6 +64,9 @@ namespace Umbraco.Web.BackOffice.Controllers _viewEngines = viewEngines; } + // TODO: This should really be refactored. Redirection/Challenge is part of Authentication, not part of authorization directly + // We only use this redirectToUmbracoLogin flag in this one instance. I think this + // should be handled as part of the preview authentication process instead. [UmbracoBackOfficeAuthorize(redirectToUmbracoLogin: true, requireApproval : false)] [DisableBrowserCache] public ActionResult Index() diff --git a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs index 482352cc74..06e4f1ad4d 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeServiceCollectionExtensions.cs @@ -118,10 +118,7 @@ namespace Umbraco.Extensions private static void AddBackOfficeAuthorizationPolicies(this IServiceCollection services) { // NOTE: Even though we are registering these handlers globally they will only actually execute their logic for - // any auth defining a matching requirement. We don't want to get in the way of end-users own aspnet logic - // and although these will trigger for any of their requests that need authorization, the logic won't actually execute. - // Basically all registered IAuthorizationHandler will execute for all requests requiring authorization but their logic - // won't trigger unless the requirement/policy matches. + // any auth defining a matching requirement and scheme. services.AddSingleton(); services.AddSingleton(); @@ -133,135 +130,245 @@ namespace Umbraco.Extensions { options.AddPolicy(AuthorizationPolicies.AdminUserEditsRequireAdmin, policy => { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); policy.Requirements.Add(new AdminUsersAuthorizeRequirement()); policy.Requirements.Add(new AdminUsersAuthorizeRequirement("userIds")); }); options.AddPolicy(AuthorizationPolicies.UserBelongsToUserGroupInRequest, policy => { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); policy.Requirements.Add(new UserGroupAuthorizeRequirement()); policy.Requirements.Add(new UserGroupAuthorizeRequirement("userGroupIds")); }); options.AddPolicy(AuthorizationPolicies.DenyLocalLoginIfConfigured, policy => - policy.Requirements.Add(new DenyLocalLoginRequirement())); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new DenyLocalLoginRequirement()); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessContent, policy => - policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Content))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Content)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessContentOrMedia, policy => - policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Content, Constants.Applications.Media))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Content, Constants.Applications.Media)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessUsers, policy => - policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Users))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Users)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessForTinyMce, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); policy.Requirements.Add(new SectionAliasesRequirement( - Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members))); + Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessMedia, policy => - policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Media))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Media)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessMembers, policy => - policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Members))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Members)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessPackages, policy => - policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Packages))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Packages)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessSettings, policy => - policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Settings))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new SectionAliasesRequirement(Constants.Applications.Settings)); + }); //We will not allow the tree to render unless the user has access to any of the sections that the tree gets rendered // this is not ideal but until we change permissions to be tree based (not section) there's not much else we can do here. options.AddPolicy(AuthorizationPolicies.SectionAccessForContentTree, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); policy.Requirements.Add(new SectionAliasesRequirement( Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Users, - Constants.Applications.Settings, Constants.Applications.Packages, Constants.Applications.Members))); + Constants.Applications.Settings, Constants.Applications.Packages, Constants.Applications.Members)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessForMediaTree, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); policy.Requirements.Add(new SectionAliasesRequirement( Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Users, - Constants.Applications.Settings, Constants.Applications.Packages, Constants.Applications.Members))); + Constants.Applications.Settings, Constants.Applications.Packages, Constants.Applications.Members)); + }); options.AddPolicy(AuthorizationPolicies.SectionAccessForMemberTree, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); policy.Requirements.Add(new SectionAliasesRequirement( - Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members))); + Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members)); + }); // Permission is granted to this policy if the user has access to any of these sections: Content, media, settings, developer, members options.AddPolicy(AuthorizationPolicies.SectionAccessForDataTypeReading, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); policy.Requirements.Add(new SectionAliasesRequirement( Constants.Applications.Content, Constants.Applications.Media, Constants.Applications.Members, - Constants.Applications.Settings, Constants.Applications.Packages))); + Constants.Applications.Settings, Constants.Applications.Packages)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessDocuments, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Content))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Content)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessUsers, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Users))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Users)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessPartialViews, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.PartialViews))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.PartialViews)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessPartialViewMacros, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.PartialViewMacros))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.PartialViewMacros)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessPackages, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Packages))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Packages)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessLogs, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.LogViewer))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.LogViewer)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessDataTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DataTypes))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DataTypes)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessTemplates, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Templates))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Templates)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessMemberTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberTypes))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberTypes)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessRelationTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.RelationTypes))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.RelationTypes)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DocumentTypes))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DocumentTypes)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessMemberGroups, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberGroups))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberGroups)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessMediaTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MediaTypes))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MediaTypes)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessMacros, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Macros))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Macros)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessLanguages, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Languages))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Languages)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessDictionary, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary, Constants.Trees.Dictionary))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary, Constants.Trees.Dictionary)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessDictionaryOrTemplates, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary, Constants.Trees.Templates))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.Dictionary, Constants.Trees.Templates)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessDocumentsOrDocumentTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DocumentTypes, Constants.Trees.Content))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DocumentTypes, Constants.Trees.Content)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessMediaOrMediaTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MediaTypes, Constants.Trees.Media))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MediaTypes, Constants.Trees.Media)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessMembersOrMemberTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberTypes, Constants.Trees.Members))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.MemberTypes, Constants.Trees.Members)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessAnySchemaTypes, policy => - policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes))); + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); + policy.Requirements.Add(new TreeAliasesRequirement(Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes)); + }); options.AddPolicy(AuthorizationPolicies.TreeAccessAnyContentOrTypes, policy => + { + policy.AuthenticationSchemes.Add(Constants.Security.BackOfficeAuthenticationType); policy.Requirements.Add(new TreeAliasesRequirement( Constants.Trees.DocumentTypes, Constants.Trees.Content, Constants.Trees.MediaTypes, Constants.Trees.Media, - Constants.Trees.MemberTypes, Constants.Trees.Members))); + Constants.Trees.MemberTypes, Constants.Trees.Members)); + }); }); } } diff --git a/src/Umbraco.Web.Common/Filters/UmbracoBackOfficeAuthorizeAttribute.cs b/src/Umbraco.Web.Common/Filters/UmbracoBackOfficeAuthorizeAttribute.cs index 1f4abbaa25..94090832bb 100644 --- a/src/Umbraco.Web.Common/Filters/UmbracoBackOfficeAuthorizeAttribute.cs +++ b/src/Umbraco.Web.Common/Filters/UmbracoBackOfficeAuthorizeAttribute.cs @@ -1,4 +1,11 @@ using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Routing; +using System; +using Umbraco.Core; +using Umbraco.Core.Hosting; +using Umbraco.Core.Security; +using Umbraco.Extensions; namespace Umbraco.Web.Common.Filters { @@ -33,5 +40,105 @@ namespace Umbraco.Web.Common.Filters { Arguments = new object[] { redirectUrl }; } + + /// + /// Ensures authorization is successful for a back office user. + /// + private class UmbracoBackOfficeAuthorizeFilter : IAuthorizationFilter + { + private readonly bool _requireApproval; + + /// + /// Can be used by unit tests to enable/disable this filter + /// + internal static bool Enable = true; + private readonly IHostingEnvironment _hostingEnvironment; + private readonly IUmbracoContextAccessor _umbracoContext; + private readonly IRuntimeState _runtimeState; + private readonly LinkGenerator _linkGenerator; + // TODO: This should really be refactored. Redirection/Challenge is part of Authentication, not part of authorization directly + // We only use this redirectToUmbracoLogin flag in this one instance. I think this + // should be handled as part of the preview authentication process instead. + private readonly bool _redirectToUmbracoLogin; + private string _redirectUrl; + + private UmbracoBackOfficeAuthorizeFilter( + IHostingEnvironment hostingEnvironment, + IUmbracoContextAccessor umbracoContext, + IRuntimeState runtimeState, LinkGenerator linkGenerator, + bool redirectToUmbracoLogin, bool requireApproval, string redirectUrl) + { + _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); + _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); + _runtimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); + _linkGenerator = linkGenerator ?? throw new ArgumentNullException(nameof(linkGenerator)); + _redirectToUmbracoLogin = redirectToUmbracoLogin; + _redirectUrl = redirectUrl; + _requireApproval = requireApproval; + } + + /// + /// Default constructor + /// + /// + /// + /// + /// + /// + public UmbracoBackOfficeAuthorizeFilter( + IHostingEnvironment hostingEnvironment, + IUmbracoContextAccessor umbracoContext, + IRuntimeState runtimeState, LinkGenerator linkGenerator, + string redirectUrl) : this(hostingEnvironment, umbracoContext, runtimeState, linkGenerator, false, false, redirectUrl) + { + } + + public UmbracoBackOfficeAuthorizeFilter( + IHostingEnvironment hostingEnvironment, + IUmbracoContextAccessor umbracoContext, + IRuntimeState runtimeState, LinkGenerator linkGenerator, + bool redirectToUmbracoLogin, bool requireApproval) : this(hostingEnvironment, umbracoContext, runtimeState, linkGenerator, redirectToUmbracoLogin, requireApproval, null) + { + } + + public void OnAuthorization(AuthorizationFilterContext context) + { + if (!IsAuthorized()) + { + if (_redirectToUmbracoLogin) + { + _redirectUrl = _linkGenerator.GetBackOfficeUrl(_hostingEnvironment); + } + + if (!_redirectUrl.IsNullOrWhiteSpace()) + { + context.Result = new RedirectResult(_redirectUrl); + } + else + { + context.Result = new ForbidResult(); + } + } + } + + private bool IsAuthorized() + { + if (Enable == false) + return true; + + try + { + // if not configured (install or upgrade) then we can continue + // otherwise we need to ensure that a user is logged in + return _runtimeState.Level == RuntimeLevel.Install + || _runtimeState.Level == RuntimeLevel.Upgrade + || _umbracoContext.UmbracoContext?.Security.ValidateCurrentUser(false, _requireApproval) == ValidateRequestAttempt.Success; + } + catch (Exception) + { + return false; + } + } + } } } diff --git a/src/Umbraco.Web.Common/Filters/UmbracoBackOfficeAuthorizeFilter.cs b/src/Umbraco.Web.Common/Filters/UmbracoBackOfficeAuthorizeFilter.cs deleted file mode 100644 index 05d46b431a..0000000000 --- a/src/Umbraco.Web.Common/Filters/UmbracoBackOfficeAuthorizeFilter.cs +++ /dev/null @@ -1,110 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Routing; -using System; -using Umbraco.Core; -using Umbraco.Core.Security; -using Umbraco.Extensions; -using Umbraco.Web.Security; -using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment; - -namespace Umbraco.Web.Common.Filters -{ - - /// - /// Ensures authorization is successful for a back office user. - /// - public class UmbracoBackOfficeAuthorizeFilter : IAuthorizationFilter - { - private readonly bool _requireApproval; - - /// - /// Can be used by unit tests to enable/disable this filter - /// - internal static bool Enable = true; - private readonly IHostingEnvironment _hostingEnvironment; - private readonly IUmbracoContextAccessor _umbracoContext; - private readonly IRuntimeState _runtimeState; - private readonly LinkGenerator _linkGenerator; - private readonly bool _redirectToUmbracoLogin; - private string _redirectUrl; - - private UmbracoBackOfficeAuthorizeFilter( - IHostingEnvironment hostingEnvironment, - IUmbracoContextAccessor umbracoContext, - IRuntimeState runtimeState, LinkGenerator linkGenerator, - bool redirectToUmbracoLogin, bool requireApproval, string redirectUrl) - { - _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); - _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); - _runtimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); - _linkGenerator = linkGenerator ?? throw new ArgumentNullException(nameof(linkGenerator)); - _redirectToUmbracoLogin = redirectToUmbracoLogin; - _redirectUrl = redirectUrl; - _requireApproval = requireApproval; - } - - /// - /// Default constructor - /// - /// - /// - /// - /// - /// - public UmbracoBackOfficeAuthorizeFilter( - IHostingEnvironment hostingEnvironment, - IUmbracoContextAccessor umbracoContext, - IRuntimeState runtimeState, LinkGenerator linkGenerator, - string redirectUrl) : this(hostingEnvironment, umbracoContext, runtimeState, linkGenerator, false, false, redirectUrl) - { - } - - public UmbracoBackOfficeAuthorizeFilter( - IHostingEnvironment hostingEnvironment, - IUmbracoContextAccessor umbracoContext, - IRuntimeState runtimeState, LinkGenerator linkGenerator, - bool redirectToUmbracoLogin, bool requireApproval) : this(hostingEnvironment, umbracoContext, runtimeState, linkGenerator, redirectToUmbracoLogin, requireApproval, null) - { - } - - public void OnAuthorization(AuthorizationFilterContext context) - { - if (!IsAuthorized()) - { - if (_redirectToUmbracoLogin) - { - _redirectUrl = _linkGenerator.GetBackOfficeUrl(_hostingEnvironment); - } - - if (!_redirectUrl.IsNullOrWhiteSpace()) - { - context.Result = new RedirectResult(_redirectUrl); - } - else - { - context.Result = new ForbidResult(); - } - } - } - - private bool IsAuthorized() - { - if (Enable == false) - return true; - - try - { - // if not configured (install or upgrade) then we can continue - // otherwise we need to ensure that a user is logged in - return _runtimeState.Level == RuntimeLevel.Install - || _runtimeState.Level == RuntimeLevel.Upgrade - || _umbracoContext.UmbracoContext?.Security.ValidateCurrentUser(false, _requireApproval) == ValidateRequestAttempt.Success; - } - catch (Exception) - { - return false; - } - } - } -}