Revert "Cleans up BackofficeSecurity, fixes up AuthenticationController for endpoints that aren't authorized (and simplifies)"
Signed-off-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
@@ -17,8 +17,6 @@ namespace Umbraco.Extensions
|
||||
/// <returns></returns>
|
||||
public static UmbracoBackOfficeIdentity GetUmbracoIdentity(this IPrincipal user)
|
||||
{
|
||||
// TODO: It would be nice to get rid of this and only rely on Claims, not a strongly typed identity instance
|
||||
|
||||
//If it's already a UmbracoBackOfficeIdentity
|
||||
if (user.Identity is UmbracoBackOfficeIdentity backOfficeIdentity) return backOfficeIdentity;
|
||||
|
||||
@@ -55,10 +53,10 @@ namespace Umbraco.Extensions
|
||||
/// <returns></returns>
|
||||
public static double GetRemainingAuthSeconds(this IPrincipal user, DateTimeOffset now)
|
||||
{
|
||||
var claimsPrincipal = user as ClaimsPrincipal;
|
||||
if (claimsPrincipal == null) return 0;
|
||||
var umbIdentity = user.GetUmbracoIdentity();
|
||||
if (umbIdentity == null) return 0;
|
||||
|
||||
var ticketExpires = claimsPrincipal.FindFirst(Constants.Security.TicketExpiresClaimType)?.Value;
|
||||
var ticketExpires = umbIdentity.FindFirstValue(Constants.Security.TicketExpiresClaimType);
|
||||
if (ticketExpires.IsNullOrWhiteSpace()) return 0;
|
||||
|
||||
var utcExpired = DateTimeOffset.Parse(ticketExpires, null, DateTimeStyles.RoundtripKind);
|
||||
|
||||
@@ -32,6 +32,13 @@ namespace Umbraco.Core.Security
|
||||
/// <returns></returns>
|
||||
ValidateRequestAttempt ValidateCurrentUser(bool throwExceptions, bool requiresApproval = true);
|
||||
|
||||
/// <summary>
|
||||
/// Authorizes the full request, checks for SSL and validates the current user
|
||||
/// </summary>
|
||||
/// <param name="throwExceptions">set to true if you want exceptions to be thrown if failed</param>
|
||||
/// <returns></returns>
|
||||
ValidateRequestAttempt AuthorizeRequest(bool throwExceptions = false);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the specified user as access to the app
|
||||
/// </summary>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
@@ -207,26 +206,18 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<double> GetRemainingTimeoutSeconds()
|
||||
public double GetRemainingTimeoutSeconds()
|
||||
{
|
||||
// force authentication to occur since this is not an authorized endpoint
|
||||
var result = await HttpContext.AuthenticateAsync(Constants.Security.BackOfficeAuthenticationType);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var backOfficeIdentity = HttpContext.User.GetUmbracoIdentity();
|
||||
var remainingSeconds = HttpContext.User.GetRemainingAuthSeconds();
|
||||
if (remainingSeconds <= 30)
|
||||
if (remainingSeconds <= 30 && backOfficeIdentity != null)
|
||||
{
|
||||
var username = result.Principal.FindFirst(ClaimTypes.Name)?.Value;
|
||||
|
||||
//NOTE: We are using 30 seconds because that is what is coded into angular to force logout to give some headway in
|
||||
// the timeout process.
|
||||
|
||||
_logger.LogInformation(
|
||||
"User logged will be logged out due to timeout: {Username}, IP Address: {IPAddress}",
|
||||
username ?? "unknown",
|
||||
backOfficeIdentity.Name,
|
||||
_ipResolver.GetCurrentRequestIpAddress());
|
||||
}
|
||||
|
||||
@@ -238,11 +229,14 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<bool> IsAuthenticated()
|
||||
public bool IsAuthenticated()
|
||||
{
|
||||
// force authentication to occur since this is not an authorized endpoint
|
||||
var result = await HttpContext.AuthenticateAsync(Constants.Security.BackOfficeAuthenticationType);
|
||||
return result.Succeeded;
|
||||
var attempt = _backofficeSecurityAccessor.BackOfficeSecurity.AuthorizeRequest();
|
||||
if (attempt == ValidateRequestAttempt.Success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -592,6 +586,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return the <see cref="UserDetail"/> for the given <see cref="IUser"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,8 @@ namespace Umbraco.Web.Common.ApplicationModels
|
||||
{
|
||||
ActionModelConventions = new List<IActionModelConvention>()
|
||||
{
|
||||
new BackOfficeIdentityCultureConvention()
|
||||
new BackOfficeIdentityCultureConvention(),
|
||||
new AuthenticateAsBackOfficeSchemeConvention()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,15 +6,8 @@ namespace Umbraco.Web.Common.Filters
|
||||
/// <summary>
|
||||
/// Ensures authorization is successful for a back office user.
|
||||
/// </summary>
|
||||
public class UmbracoBackOfficeAuthorizeAttribute : TypeFilterAttribute, IAuthorizeData
|
||||
public class UmbracoBackOfficeAuthorizeAttribute : TypeFilterAttribute
|
||||
{
|
||||
// Implements IAuthorizeData to return the back office scheme so that all requests with this attributes
|
||||
// get authenticated with this scheme.
|
||||
// TODO: We'll have to refactor this as part of the authz policy changes.
|
||||
public string AuthenticationSchemes { get; set; } = Umbraco.Core.Constants.Security.BackOfficeAuthenticationType;
|
||||
public string Policy { get; set; }
|
||||
public string Roles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
|
||||
@@ -52,6 +52,18 @@ namespace Umbraco.Web.Common.Security
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValidateRequestAttempt AuthorizeRequest(bool throwExceptions = false)
|
||||
{
|
||||
// check for secure connection
|
||||
if (_globalSettings.UseHttps && !_httpContextAccessor.GetRequiredHttpContext().Request.IsHttps)
|
||||
{
|
||||
if (throwExceptions) throw new SecurityException("This installation requires a secure connection (via SSL). Please update the URL to include https://");
|
||||
return ValidateRequestAttempt.FailedNoSsl;
|
||||
}
|
||||
return ValidateCurrentUser(throwExceptions);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Attempt<int> GetUserId()
|
||||
{
|
||||
@@ -94,7 +106,6 @@ namespace Umbraco.Web.Common.Security
|
||||
|
||||
var user = CurrentUser;
|
||||
|
||||
// TODO: All of this is done as part of identity/backofficesigninmanager
|
||||
// Check for console access
|
||||
if (user == null || (requiresApproval && user.IsApproved == false) || (user.IsLockedOut && RequestIsInUmbracoApplication(_httpContextAccessor, _globalSettings, _hostingEnvironment)))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user