Ensures that all back office controllers are authenticated under the back office scheme
This commit is contained in:
@@ -45,7 +45,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)] // TODO: Maybe this could be applied with our Application Model conventions
|
||||
//[ValidationFilter] // TODO: I don't actually think this is required with our custom Application Model conventions applied
|
||||
[AngularJsonOnlyConfiguration] // TODO: This could be applied with our Application Model conventions
|
||||
[IsBackOffice] // TODO: This could be applied with our Application Model conventions
|
||||
[IsBackOffice]
|
||||
public class AuthenticationController : UmbracoApiControllerBase
|
||||
{
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
[DisableBrowserCache]
|
||||
//[UmbracoRequireHttps] //TODO Reintroduce
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeArea)]
|
||||
[IsBackOffice]
|
||||
public class BackOfficeController : UmbracoController
|
||||
{
|
||||
private readonly IBackOfficeUserManager _userManager;
|
||||
|
||||
@@ -8,8 +8,7 @@ using Umbraco.Web.PublishedCache;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[IsBackOffice]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class PublishedSnapshotCacheStatusController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
|
||||
@@ -32,15 +32,9 @@ namespace Umbraco.Extensions
|
||||
builder.Services.AddAntiforgery();
|
||||
builder.Services.AddSingleton<IFilterProvider, OverrideAuthorizationFilterProvider>();
|
||||
|
||||
// TODO: We need to see if we are 'allowed' to do this, the docs say:
|
||||
// "The call to AddIdentity configures the default scheme settings. The AddAuthentication(String) overload sets the DefaultScheme property. The AddAuthentication(Action<AuthenticationOptions>) overload allows configuring authentication options, which can be used to set up default authentication schemes for different purposes. Subsequent calls to AddAuthentication override previously configured AuthenticationOptions properties."
|
||||
// So if someone calls services.AddAuthentication() ... in Startup does that overwrite all of this?
|
||||
// It also says "When the app requires multiple providers, chain the provider extension methods behind AddAuthentication"
|
||||
// Which leads me to believe it all gets overwritten? :/
|
||||
// UPDATE: I have tested this breifly in Startup doing Services.AddAuthentication().AddGoogle() ... and the back office auth
|
||||
// still seems to work. We'll see how it goes i guess.
|
||||
builder.Services
|
||||
.AddAuthentication(Core.Constants.Security.BackOfficeAuthenticationType)
|
||||
.AddAuthentication() // This just creates a builder, nothing more
|
||||
// Add our custom schemes which are cookie handlers
|
||||
.AddCookie(Core.Constants.Security.BackOfficeAuthenticationType)
|
||||
.AddCookie(Core.Constants.Security.BackOfficeExternalAuthenticationType, o =>
|
||||
{
|
||||
|
||||
@@ -26,6 +26,11 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
_loginProviderOptions = loginProviderOptions;
|
||||
}
|
||||
|
||||
public string SchemeForBackOffice(string scheme)
|
||||
{
|
||||
return Constants.Security.BackOfficeExternalAuthenticationTypePrefix + scheme;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridden to track the final authenticationScheme being registered for the external login
|
||||
/// </summary>
|
||||
@@ -36,11 +41,11 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
/// <param name="configureOptions"></param>
|
||||
/// <returns></returns>
|
||||
public override AuthenticationBuilder AddRemoteScheme<TOptions, THandler>(string authenticationScheme, string displayName, Action<TOptions> configureOptions)
|
||||
{
|
||||
//Ensure the prefix is set
|
||||
{
|
||||
// Validate that the prefix is set
|
||||
if (!authenticationScheme.StartsWith(Constants.Security.BackOfficeExternalAuthenticationTypePrefix))
|
||||
{
|
||||
authenticationScheme = Constants.Security.BackOfficeExternalAuthenticationTypePrefix + authenticationScheme;
|
||||
throw new InvalidOperationException($"The {nameof(authenticationScheme)} is not prefixed with {Constants.Security.BackOfficeExternalAuthenticationTypePrefix}. The scheme must be created with a call to the method {nameof(SchemeForBackOffice)}");
|
||||
}
|
||||
|
||||
// add our login provider to the container along with a custom options configuration
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Umbraco.Web.Common.Filters;
|
||||
|
||||
namespace Umbraco.Web.Common.ApplicationModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures all requests with this convention are authenticated with the back office scheme
|
||||
/// </summary>
|
||||
public class AuthenticateAsBackOfficeSchemeConvention : IActionModelConvention
|
||||
{
|
||||
public void Apply(ActionModel action)
|
||||
{
|
||||
action.Filters.Add(new EnsureUmbracoBackOfficeAuthentication());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ using Umbraco.Web.Common.Attributes;
|
||||
|
||||
namespace Umbraco.Web.Common.ApplicationModels
|
||||
{
|
||||
// TODO: This should just exist in the back office project
|
||||
|
||||
/// <summary>
|
||||
/// An application model provider for all Umbraco Back Office controllers
|
||||
/// </summary>
|
||||
@@ -15,7 +17,8 @@ namespace Umbraco.Web.Common.ApplicationModels
|
||||
{
|
||||
ActionModelConventions = new List<IActionModelConvention>()
|
||||
{
|
||||
new BackOfficeIdentityCultureConvention()
|
||||
new BackOfficeIdentityCultureConvention(),
|
||||
new AuthenticateAsBackOfficeSchemeConvention()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,12 +52,7 @@ namespace Umbraco.Web.Common.ApplicationModels
|
||||
}
|
||||
|
||||
private bool IsBackOfficeController(ControllerModel controller)
|
||||
{
|
||||
var pluginControllerAttribute = controller.Attributes.OfType<PluginControllerAttribute>().FirstOrDefault();
|
||||
return pluginControllerAttribute != null
|
||||
&& (pluginControllerAttribute.AreaName == Core.Constants.Web.Mvc.BackOfficeArea
|
||||
|| pluginControllerAttribute.AreaName == Core.Constants.Web.Mvc.BackOfficeApiArea
|
||||
|| pluginControllerAttribute.AreaName == Core.Constants.Web.Mvc.BackOfficeTreeArea);
|
||||
}
|
||||
=> controller.Attributes.OfType<IsBackOfficeAttribute>().Any();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ using Umbraco.Web.Common.Filters;
|
||||
|
||||
namespace Umbraco.Web.Common.ApplicationModels
|
||||
{
|
||||
|
||||
// TODO: This should just exist in the back office project
|
||||
|
||||
public class BackOfficeIdentityCultureConvention : IActionModelConvention
|
||||
{
|
||||
public void Apply(ActionModel action)
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace Umbraco.Web.Common.ApplicationModels
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsUmbracoApiController(ControllerModel controller) => controller.Attributes.OfType<UmbracoApiControllerAttribute>().Any();
|
||||
private bool IsUmbracoApiController(ControllerModel controller)
|
||||
=> controller.Attributes.OfType<UmbracoApiControllerAttribute>().Any();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Umbraco.Web.Common.ModelBinding;
|
||||
using System.Linq;
|
||||
using Umbraco.Web.Common.Attributes;
|
||||
using Umbraco.Web.Actions;
|
||||
using Umbraco.Web.Common.Filters;
|
||||
|
||||
namespace Umbraco.Web.Common.ApplicationModels
|
||||
{
|
||||
@@ -21,4 +24,6 @@ namespace Umbraco.Web.Common.ApplicationModels
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Umbraco.Web.Common.ApplicationModels;
|
||||
using Umbraco.Web.Common.Attributes;
|
||||
|
||||
namespace Umbraco.Web.Common.Filters
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Assigned as part of the umbraco back office application model <see cref="UmbracoApiBehaviorApplicationModelProvider"/>
|
||||
/// to always ensure that back office authentication occurs for all controller/actions with
|
||||
/// <see cref="IsBackOfficeAttribute"/> applied.
|
||||
/// </summary>
|
||||
public class EnsureUmbracoBackOfficeAuthentication : IAuthorizationFilter, IAuthorizeData
|
||||
{
|
||||
// Implements IAuthorizeData only to return the back office scheme
|
||||
public string AuthenticationSchemes { get; set; } = Umbraco.Core.Constants.Security.BackOfficeAuthenticationType;
|
||||
public string Policy { get; set; }
|
||||
public string Roles { get; set; }
|
||||
|
||||
public void OnAuthorization(AuthorizationFilterContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Umbraco.Web.Common.Filters
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@ using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment;
|
||||
namespace Umbraco.Web.Common.Filters
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ensures authorization is successful for a back office user.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user