Merge remote-tracking branch 'origin/netcore/netcore' into netcore/feature/migrate-remaining-trees
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.BackOffice;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.Net;
|
||||
using Umbraco.Web.BackOffice.Filters;
|
||||
using Umbraco.Web.Common.Attributes;
|
||||
using Umbraco.Web.Common.Controllers;
|
||||
@@ -33,6 +37,8 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
private readonly IUserService _userService;
|
||||
private readonly UmbracoMapper _umbracoMapper;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IIpResolver _ipResolver;
|
||||
|
||||
// TODO: We need to import the logic from Umbraco.Web.Editors.AuthenticationController
|
||||
// TODO: We need to review all _userManager.Raise calls since many/most should be on the usermanager or signinmanager, very few should be here
|
||||
@@ -43,7 +49,8 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
BackOfficeSignInManager signInManager,
|
||||
IUserService userService,
|
||||
UmbracoMapper umbracoMapper,
|
||||
IGlobalSettings globalSettings)
|
||||
IGlobalSettings globalSettings,
|
||||
ILogger logger, IIpResolver ipResolver)
|
||||
{
|
||||
_webSecurity = webSecurity;
|
||||
_userManager = backOfficeUserManager;
|
||||
@@ -51,6 +58,27 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
_userService = userService;
|
||||
_umbracoMapper = umbracoMapper;
|
||||
_globalSettings = globalSettings;
|
||||
_logger = logger;
|
||||
_ipResolver = ipResolver;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public double GetRemainingTimeoutSeconds()
|
||||
{
|
||||
var backOfficeIdentity = HttpContext.User.GetUmbracoIdentity();
|
||||
var remainingSeconds = HttpContext.User.GetRemainingAuthSeconds();
|
||||
if (remainingSeconds <= 30 && backOfficeIdentity != null)
|
||||
{
|
||||
//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.Info<AuthenticationController>(
|
||||
"User logged will be logged out due to timeout: {Username}, IP Address: {IPAddress}",
|
||||
backOfficeIdentity.Name,
|
||||
_ipResolver.GetCurrentRequestIpAddress());
|
||||
}
|
||||
|
||||
return remainingSeconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -156,6 +184,22 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
throw new HttpResponseException(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the current user out
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[TypeFilter(typeof(ValidateAngularAntiForgeryTokenAttribute))]
|
||||
public IActionResult PostLogout()
|
||||
{
|
||||
HttpContext.SignOutAsync(Core.Constants.Security.BackOfficeAuthenticationType);
|
||||
|
||||
_logger.Info<AuthenticationController>("User {UserName} from IP address {RemoteIpAddress} has logged out", User.Identity == null ? "UNKNOWN" : User.Identity.Name, HttpContext.Connection.RemoteIpAddress);
|
||||
|
||||
_userManager.RaiseLogoutSuccessEvent(User, int.Parse(User.Identity.GetUserId()));
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the <see cref="UserDetail"/> for the given <see cref="IUser"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -11,7 +12,7 @@ using Umbraco.Web.Common.Attributes;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class BackOfficeAssetsController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IFileSystem _jsLibFileSystem;
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
// TODO: Put some exception filters in our webapi to return 404 instead of 500 when we throw ArgumentNullException
|
||||
// ref: https://www.exceptionnotfound.net/the-asp-net-web-api-exception-handling-pipeline-a-guided-tour/
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
//[PrefixlessBodyModelValidator]
|
||||
[UmbracoApplicationAuthorizeAttribute(Constants.Applications.Settings)]
|
||||
public class CodeFileController : BackOfficeNotificationsController
|
||||
|
||||
@@ -25,7 +25,7 @@ using Umbraco.Web.WebApi.Filters;
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
//we need to fire up the controller like this to enable loading of remote css directly from this controller
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[ValidationFilter]
|
||||
[AngularJsonOnlyConfiguration] // TODO: This could be applied with our Application Model conventions
|
||||
[IsBackOffice]
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// The security for this controller is defined to allow full CRUD access to data types if the user has access to either:
|
||||
/// Content Types, Member Types or Media Types ... and of course to Data Types
|
||||
/// </remarks>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[UmbracoTreeAuthorizeAttribute(Constants.Trees.DataTypes, Constants.Trees.DocumentTypes, Constants.Trees.MediaTypes, Constants.Trees.MemberTypes)]
|
||||
public class DataTypeController : BackOfficeNotificationsController
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// The security for this controller is defined to allow full CRUD access to dictionary if the user has access to either:
|
||||
/// Dictionary
|
||||
/// </remarks>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[UmbracoTreeAuthorize(Constants.Trees.Dictionary)]
|
||||
public class DictionaryController : BackOfficeNotificationsController
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ using SearchResult = Umbraco.Web.Models.ContentEditing.SearchResult;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class ExamineManagementController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IExamineManager _examineManager;
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Media;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Common.Attributes;
|
||||
@@ -22,7 +23,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// building to generate correct URLs
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class ImageUrlGeneratorController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IImageUrlGenerator _imageUrlGenerator;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Media;
|
||||
@@ -13,7 +14,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// A controller used to return images for media
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class ImagesController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly IMediaFileSystem _mediaFileSystem;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Backoffice controller supporting the dashboard for language administration.
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
//[PrefixlessBodyModelValidator]
|
||||
public class LanguageController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// The API controller used for getting log history
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class LogController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IMediaFileSystem _mediaFileSystem;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// Backoffice controller supporting the dashboard for viewing logs with some simple graphs & filtering
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class LogViewerController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly ILogViewer _logViewer;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// A controller used for managing packages in the back office
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[UmbracoApplicationAuthorizeAttribute(Constants.Applications.Packages)]
|
||||
public class PackageController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// A controller used for installing packages and managing all of the data in the packages section in the back office
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[UmbracoApplicationAuthorizeAttribute(Constants.Applications.Packages)]
|
||||
public class PackageInstallController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class RedirectUrlManagementController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
@@ -17,7 +17,7 @@ using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[UmbracoApplicationAuthorizeAttribute(Constants.Applications.Content)]
|
||||
public class RelationController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// The API controller for editing relation types.
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[UmbracoTreeAuthorizeAttribute(Constants.Trees.RelationTypes)]
|
||||
public class RelationTypeController : BackOfficeNotificationsController
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -17,7 +18,7 @@ namespace Umbraco.Web.Editors
|
||||
/// <summary>
|
||||
/// The API controller used for using the list of sections
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class SectionController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IControllerFactory _controllerFactory;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Web.BackOffice.Controllers
|
||||
/// <summary>
|
||||
/// The API controller used for retrieving available stylesheets
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class StylesheetController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IFileService _fileService;
|
||||
|
||||
@@ -16,7 +16,7 @@ using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[UmbracoTreeAuthorizeAttribute(Constants.Trees.Templates)]
|
||||
public class TemplateController : BackOfficeNotificationsController
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ using Constants = Umbraco.Core.Constants;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
[UmbracoApplicationAuthorize(
|
||||
Constants.Applications.Content,
|
||||
Constants.Applications.Media,
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -13,7 +14,7 @@ using Umbraco.Web.Tour;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class TourController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly TourFilterCollection _filters;
|
||||
|
||||
@@ -15,7 +15,7 @@ using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Controllers
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class UpdateCheckController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IUpgradeService _upgradeService;
|
||||
|
||||
@@ -23,6 +23,9 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
services.AddAntiforgery();
|
||||
|
||||
// TODO: We had this check in v8 where we don't enable these unless we can run...
|
||||
//if (runtimeState.Level != RuntimeLevel.Upgrade && runtimeState.Level != RuntimeLevel.Run) return app;
|
||||
|
||||
services
|
||||
.AddAuthentication(Constants.Security.BackOfficeAuthenticationType)
|
||||
.AddCookie(Constants.Security.BackOfficeAuthenticationType);
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace Umbraco.Web.BackOffice.Filters
|
||||
/// </remarks>
|
||||
public sealed class ValidateAngularAntiForgeryTokenAttribute : ActionFilterAttribute
|
||||
{
|
||||
// TODO: Either make this inherit from TypeFilter or make this just a normal IActionFilter
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly IBackOfficeAntiforgery _antiforgery;
|
||||
private readonly ICookieManager _cookieManager;
|
||||
|
||||
@@ -4,10 +4,11 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Common.Attributes;
|
||||
using Umbraco.Web.BackOffice.Controllers;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.PropertyEditors
|
||||
{
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class NestedContentController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Umbraco.Web.BackOffice.PropertyEditors
|
||||
/// <summary>
|
||||
/// ApiController to provide RTE configuration with available plugins and commands from the RTE config
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class RichTextPreValueController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
|
||||
@@ -5,13 +5,14 @@ using Umbraco.Web.BackOffice.Controllers;
|
||||
using Umbraco.Core.Media;
|
||||
using Umbraco.Web.Common.Attributes;
|
||||
using Umbraco.Web.Media.EmbedProviders;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// A controller used for the embed dialog
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class RteEmbedController : UmbracoAuthorizedJsonController
|
||||
{
|
||||
private readonly EmbedProvidersCollection _embedCollection;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Umbraco.Web.BackOffice.PropertyEditors
|
||||
/// DO NOT inherit from UmbracoAuthorizedJsonController since we don't want to use the angularized
|
||||
/// json formatter as it causes problems.
|
||||
/// </remarks>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
|
||||
public class TagsDataController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly ITagQuery _tagQuery;
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Web.BackOffice.Controllers;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Security
|
||||
{
|
||||
@@ -20,7 +23,7 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
/// Umbraco's back office cookie needs to be read on two paths: /umbraco and /install and /base therefore we cannot just set the cookie path to be /umbraco,
|
||||
/// instead we'll specify our own cookie manager and return null if the request isn't for an acceptable path.
|
||||
/// </remarks>
|
||||
internal class BackOfficeCookieManager : ChunkingCookieManager, ICookieManager
|
||||
public class BackOfficeCookieManager : ChunkingCookieManager, ICookieManager
|
||||
{
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly IRuntimeState _runtime;
|
||||
@@ -28,13 +31,25 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly IRequestCache _requestCache;
|
||||
private readonly string[] _explicitPaths;
|
||||
private readonly string _getRemainingSecondsPath;
|
||||
|
||||
public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IHostingEnvironment hostingEnvironment, IGlobalSettings globalSettings, IRequestCache requestCache)
|
||||
: this(umbracoContextAccessor, runtime, hostingEnvironment, globalSettings, requestCache, null)
|
||||
public BackOfficeCookieManager(
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
IRuntimeState runtime,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IGlobalSettings globalSettings,
|
||||
IRequestCache requestCache,
|
||||
LinkGenerator linkGenerator)
|
||||
: this(umbracoContextAccessor, runtime, hostingEnvironment, globalSettings, requestCache, linkGenerator, null)
|
||||
{ }
|
||||
|
||||
public BackOfficeCookieManager(IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IHostingEnvironment hostingEnvironment, IGlobalSettings globalSettings, IRequestCache requestCache, IEnumerable<string> explicitPaths)
|
||||
public BackOfficeCookieManager(
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
IRuntimeState runtime,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IGlobalSettings globalSettings,
|
||||
IRequestCache requestCache,
|
||||
LinkGenerator linkGenerator,
|
||||
IEnumerable<string> explicitPaths)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_runtime = runtime;
|
||||
@@ -42,9 +57,6 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
_globalSettings = globalSettings;
|
||||
_requestCache = requestCache;
|
||||
_explicitPaths = explicitPaths?.ToArray();
|
||||
var backOfficePath = _globalSettings.GetBackOfficePath(_hostingEnvironment);
|
||||
// TODO: We shouldn't hard code this path
|
||||
_getRemainingSecondsPath = $"{backOfficePath}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -60,7 +72,7 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
/// * it is a /base request
|
||||
/// * it is a preview request
|
||||
/// </remarks>
|
||||
internal bool ShouldAuthenticateRequest(Uri requestUri, bool checkForceAuthTokens = true)
|
||||
public bool ShouldAuthenticateRequest(Uri requestUri, bool checkForceAuthTokens = true)
|
||||
{
|
||||
// Do not authenticate the request if we are not running (don't have a db, are not configured) - since we will never need
|
||||
// to know a current user in this scenario - we treat it as a new install. Without this we can have some issues
|
||||
@@ -75,9 +87,6 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
if (_explicitPaths != null)
|
||||
return _explicitPaths.Any(x => x.InvariantEquals(requestUri.AbsolutePath));
|
||||
|
||||
//check user seconds path
|
||||
if (requestUri.AbsolutePath.InvariantEquals(_getRemainingSecondsPath)) return false;
|
||||
|
||||
if (//check the explicit flag
|
||||
checkForceAuthTokens && _requestCache.IsAvailable && _requestCache.Get(Constants.Security.ForceReAuthFlag) != null
|
||||
//check back office
|
||||
|
||||
@@ -9,7 +9,6 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
/// <summary>
|
||||
/// Custom secure format that ensures the Identity in the ticket is <see cref="UmbracoBackOfficeIdentity"/> and not just a ClaimsIdentity
|
||||
/// </summary>
|
||||
// TODO: Unsure if we really need this, there's no real reason why we have a custom Identity instead of just a ClaimsIdentity
|
||||
internal class BackOfficeSecureDataFormat : ISecureDataFormat<AuthenticationTicket>
|
||||
{
|
||||
private readonly int _loginTimeoutMinutes;
|
||||
@@ -23,7 +22,7 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
|
||||
public string Protect(AuthenticationTicket data, string purpose)
|
||||
{
|
||||
//create a new ticket based on the passed in tickets details, however, we'll adjust the expires utc based on the specified timeout mins
|
||||
// create a new ticket based on the passed in tickets details, however, we'll adjust the expires utc based on the specified timeout mins
|
||||
var ticket = new AuthenticationTicket(data.Principal,
|
||||
new AuthenticationProperties(data.Properties.Items)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@ using Umbraco.Core.Security;
|
||||
using Umbraco.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Web.Common.Security;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Security
|
||||
{
|
||||
@@ -35,7 +36,9 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
private readonly IRequestCache _requestCache;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IIpResolver _ipResolver;
|
||||
private readonly ISystemClock _systemClock;
|
||||
private readonly BackOfficeSessionIdValidator _sessionIdValidator;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
|
||||
public ConfigureBackOfficeCookieOptions(
|
||||
IUmbracoContextAccessor umbracoContextAccessor,
|
||||
@@ -47,7 +50,9 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
IRequestCache requestCache,
|
||||
IUserService userService,
|
||||
IIpResolver ipResolver,
|
||||
BackOfficeSessionIdValidator sessionIdValidator)
|
||||
ISystemClock systemClock,
|
||||
BackOfficeSessionIdValidator sessionIdValidator,
|
||||
LinkGenerator linkGenerator)
|
||||
{
|
||||
_umbracoContextAccessor = umbracoContextAccessor;
|
||||
_securitySettings = securitySettings;
|
||||
@@ -58,7 +63,9 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
_requestCache = requestCache;
|
||||
_userService = userService;
|
||||
_ipResolver = ipResolver;
|
||||
_systemClock = systemClock;
|
||||
_sessionIdValidator = sessionIdValidator;
|
||||
_linkGenerator = linkGenerator;
|
||||
}
|
||||
|
||||
public void Configure(string name, CookieAuthenticationOptions options)
|
||||
@@ -98,7 +105,8 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
_runtimeState,
|
||||
_hostingEnvironment,
|
||||
_globalSettings,
|
||||
_requestCache);
|
||||
_requestCache,
|
||||
_linkGenerator);
|
||||
// _explicitPaths); TODO: Implement this once we do OAuth somehow
|
||||
|
||||
|
||||
@@ -111,7 +119,7 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
// It would be possible to re-use the default behavior if any of these need to be set but that must be taken into account else
|
||||
// our back office requests will not function correctly. For now we don't need to set/configure any of these callbacks because
|
||||
// the defaults work fine with our setup.
|
||||
|
||||
|
||||
OnValidatePrincipal = async ctx =>
|
||||
{
|
||||
// We need to resolve the BackOfficeSecurityStampValidator per request as a requirement (even in aspnetcore they do this)
|
||||
@@ -131,6 +139,7 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
|
||||
await EnsureValidSessionId(ctx);
|
||||
await securityStampValidator.ValidateAsync(ctx);
|
||||
EnsureTicketRenewalIfKeepUserLoggedIn(ctx);
|
||||
|
||||
// add a claim to track when the cookie expires, we use this to track time remaining
|
||||
backOfficeIdentity.AddClaim(new Claim(
|
||||
@@ -140,7 +149,7 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
UmbracoBackOfficeIdentity.Issuer,
|
||||
UmbracoBackOfficeIdentity.Issuer,
|
||||
backOfficeIdentity));
|
||||
|
||||
|
||||
},
|
||||
OnSigningIn = ctx =>
|
||||
{
|
||||
@@ -175,7 +184,6 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
OnSigningOut = ctx =>
|
||||
{
|
||||
//Clear the user's session on sign out
|
||||
// TODO: We need to test this once we have signout functionality, not sure if the httpcontext.user.identity will still be set here
|
||||
if (ctx.HttpContext?.User?.Identity != null)
|
||||
{
|
||||
var claimsIdentity = ctx.HttpContext.User.Identity as ClaimsIdentity;
|
||||
@@ -192,7 +200,9 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
BackOfficeSessionIdValidator.CookieName,
|
||||
_securitySettings.AuthCookieName,
|
||||
Constants.Web.PreviewCookieName,
|
||||
Constants.Security.BackOfficeExternalCookieName
|
||||
Constants.Security.BackOfficeExternalCookieName,
|
||||
Constants.Web.AngularCookieName,
|
||||
Constants.Web.CsrfValidationCookieName,
|
||||
};
|
||||
foreach (var cookie in cookies)
|
||||
{
|
||||
@@ -218,5 +228,31 @@ namespace Umbraco.Web.BackOffice.Security
|
||||
if (_runtimeState.Level == RuntimeLevel.Run)
|
||||
await _sessionIdValidator.ValidateSessionAsync(TimeSpan.FromMinutes(1), context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures the ticket is renewed if the <see cref="ISecuritySettings.KeepUserLoggedIn"/> is set to true
|
||||
/// and the current request is for the get user seconds endpoint
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
private void EnsureTicketRenewalIfKeepUserLoggedIn(CookieValidatePrincipalContext context)
|
||||
{
|
||||
if (!_securitySettings.KeepUserLoggedIn) return;
|
||||
|
||||
var currentUtc = _systemClock.UtcNow;
|
||||
var issuedUtc = context.Properties.IssuedUtc;
|
||||
var expiresUtc = context.Properties.ExpiresUtc;
|
||||
|
||||
if (expiresUtc.HasValue && issuedUtc.HasValue)
|
||||
{
|
||||
var timeElapsed = currentUtc.Subtract(issuedUtc.Value);
|
||||
var timeRemaining = expiresUtc.Value.Subtract(currentUtc);
|
||||
|
||||
//if it's time to renew, then do it
|
||||
if (timeRemaining < timeElapsed)
|
||||
{
|
||||
context.ShouldRenew = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user