From 42d571113242176c59077b4d97bcbc05699b0de5 Mon Sep 17 00:00:00 2001 From: Elitsa Date: Thu, 12 Oct 2023 08:20:52 +0200 Subject: [PATCH 1/8] Add new config options --- src/Umbraco.Core/Configuration/Models/SecuritySettings.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs b/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs index 5b36de1bfa72..7c693b51c0b1 100644 --- a/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs +++ b/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs @@ -17,6 +17,7 @@ public class SecuritySettings internal const bool StaticHideDisabledUsersInBackOffice = false; internal const bool StaticAllowPasswordReset = true; internal const bool StaticAllowEditInvariantFromNonDefault = false; + internal const bool StaticAllowConcurrentLogins = true; internal const string StaticAuthCookieName = "UMB_UCONTEXT"; internal const string StaticAllowedUserNameCharacters = @@ -109,4 +110,10 @@ public class SecuritySettings [Obsolete("Use ContentSettings.AllowEditFromInvariant instead")] [DefaultValue(StaticAllowEditInvariantFromNonDefault)] public bool AllowEditInvariantFromNonDefault { get; set; } = StaticAllowEditInvariantFromNonDefault; + + /// + /// Gets or sets a value indicating whether to allow concurrent logins. + /// + [DefaultValue(StaticAllowConcurrentLogins)] + public bool AllowConcurrentLogins { get; set; } = StaticAllowConcurrentLogins; } From aa97660f1d25040862d9c3816fc5b61df2eaa431 Mon Sep 17 00:00:00 2001 From: Elitsa Date: Thu, 12 Oct 2023 08:21:21 +0200 Subject: [PATCH 2/8] Change validation interval + related changes --- ...BackOfficeSecurityStampValidatorOptions.cs | 13 ++++++--- .../Security/ConfigureSecurityStampOptions.cs | 27 ++++++++++++++++--- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs index ec5f0f669686..dcfd02c008e8 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs @@ -1,14 +1,19 @@ using Microsoft.Extensions.Options; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Web.Common.Security; namespace Umbraco.Cms.Web.BackOffice.Security; /// -/// Configures the back office security stamp options +/// Configures the back office security stamp options. /// -public class - ConfigureBackOfficeSecurityStampValidatorOptions : IConfigureOptions +public class ConfigureBackOfficeSecurityStampValidatorOptions : IConfigureOptions { + private readonly SecuritySettings _securitySettings; + + public ConfigureBackOfficeSecurityStampValidatorOptions(IOptionsMonitor securitySettings) + => _securitySettings = securitySettings.CurrentValue; + public void Configure(BackOfficeSecurityStampValidatorOptions options) - => ConfigureSecurityStampOptions.ConfigureOptions(options); + => ConfigureSecurityStampOptions.ConfigureOptions(options, _securitySettings); } diff --git a/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs b/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs index 5cebab43b978..6b5330a089ec 100644 --- a/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs +++ b/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs @@ -1,20 +1,39 @@ using System.Security.Claims; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Extensions; namespace Umbraco.Cms.Web.Common.Security; public class ConfigureSecurityStampOptions : IConfigureOptions { + private readonly SecuritySettings _securitySettings; + + public ConfigureSecurityStampOptions(IOptionsMonitor securitySettings) + => _securitySettings = securitySettings.CurrentValue; + + [Obsolete("Use the overload accepting SecuritySettings instead. Scheduled for removal in v14.")] + public static void ConfigureOptions(SecurityStampValidatorOptions options) + => ConfigureOptions(options, StaticServiceProvider.Instance.GetRequiredService()); + /// /// Configures security stamp options and ensures any custom claims /// set on the identity are persisted to the new identity when it's refreshed. /// - /// - public static void ConfigureOptions(SecurityStampValidatorOptions options) + /// Options for . + /// The options. + public static void ConfigureOptions(SecurityStampValidatorOptions options, SecuritySettings securitySettings) { - options.ValidationInterval = TimeSpan.FromMinutes(30); + // Adjust the security stamp validation interval to a shorter duration + // when concurrent logins are not allowed and the duration has the default interval value + // (currently defaults to 30 minutes), ensuring quicker re-validation. + if (!securitySettings.AllowConcurrentLogins && options.ValidationInterval == TimeSpan.FromMinutes(30)) + { + options.ValidationInterval = TimeSpan.FromSeconds(5); + } // When refreshing the principal, ensure custom claims that // might have been set with an external identity continue @@ -35,5 +54,5 @@ public static void ConfigureOptions(SecurityStampValidatorOptions options) } public void Configure(SecurityStampValidatorOptions options) - => ConfigureOptions(options); + => ConfigureOptions(options, _securitySettings); } From 21c848827b3ff21516b968596feab21eecf2e79d Mon Sep 17 00:00:00 2001 From: Elitsa Date: Thu, 12 Oct 2023 08:21:38 +0200 Subject: [PATCH 3/8] Fix typo --- src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs b/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs index 6a167b39f7c4..8a94e7e51220 100644 --- a/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs +++ b/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs @@ -10,7 +10,7 @@ namespace Umbraco.Cms.Web.Common.Security; /// -/// Abstract sign in manager implementation allowing modifying all defeault authentication schemes +/// Abstract sign in manager implementation allowing modifying all default authentication schemes. /// /// public abstract class UmbracoSignInManager : SignInManager From 5e5265f239f068a56f498e5bb6b3d0a5e5c6c7e9 Mon Sep 17 00:00:00 2001 From: Elitsa Date: Thu, 12 Oct 2023 08:23:09 +0200 Subject: [PATCH 4/8] Temp fix --- .../Security/ConfigureBackOfficeCookieOptions.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs index 02b0409ed33f..8265f493e7b0 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs @@ -11,9 +11,11 @@ using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Net; using Umbraco.Cms.Core.Routing; +using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Web.BackOffice.Controllers; +using Umbraco.Cms.Web.Common.Security; using Umbraco.Extensions; namespace Umbraco.Cms.Web.BackOffice.Security; @@ -221,6 +223,20 @@ public void Configure(CookieAuthenticationOptions options) Constants.Security.BackOfficeAuthenticationType, Constants.Security.BackOfficeAuthenticationType, backOfficeIdentity)); + + // Update the security stamp when sign-in is successful + var userManager = ctx.HttpContext.RequestServices.GetRequiredService(); + + // TODO: check if securitySettings.AllowConcurrentLogins is not allowed + if (ctx.Principal != null) + { + BackOfficeIdentityUser? user = userManager.GetUserAsync(ctx.Principal).GetAwaiter().GetResult(); + + if (user is not null) + { + userManager.UpdateSecurityStampAsync(user).GetAwaiter().GetResult(); + } + } } return Task.CompletedTask; From 53292c2ea40ba53409a46db0771097574a788027 Mon Sep 17 00:00:00 2001 From: Elitsa Date: Thu, 12 Oct 2023 08:23:35 +0200 Subject: [PATCH 5/8] Set new setting to false for new dotnet projects --- templates/UmbracoProject/appsettings.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/templates/UmbracoProject/appsettings.json b/templates/UmbracoProject/appsettings.json index 03457ad0b742..667847895197 100644 --- a/templates/UmbracoProject/appsettings.json +++ b/templates/UmbracoProject/appsettings.json @@ -36,6 +36,9 @@ }, "Unattended": { "UpgradeUnattended": true + }, + "Security": { + "AllowConcurrentLogins": false } } } From af11fef4553945e48e255bfa10cb530280a4d30c Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 12 Oct 2023 15:33:05 +0200 Subject: [PATCH 6/8] Added logic to update security stamp on sign in + fixed wierd code calling handle signIn twice --- .../Security/BackOfficeSignInManager.cs | 26 +++++++++++--- .../ConfigureBackOfficeCookieOptions.cs | 16 --------- .../Security/MemberSignInManager.cs | 35 +++++++++++++++++-- .../Security/UmbracoSignInManager.cs | 28 ++++++++++++++- .../Security/MemberSignInManagerTests.cs | 4 ++- 5 files changed, 84 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs index 81fe5b5aa08c..79bccb6edb00 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs @@ -36,8 +36,9 @@ public BackOfficeSignInManager( ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation, - IEventAggregator eventAggregator) - : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) + IEventAggregator eventAggregator, + IOptions securitySettings) + : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation, securitySettings) { _userManager = userManager; _externalLogins = externalLogins; @@ -45,7 +46,24 @@ public BackOfficeSignInManager( _globalSettings = globalSettings.Value; } - [Obsolete("Use ctor with all params")] + [Obsolete("Use non-obsolete constructor. This is scheduled for removal in V14.")] + public BackOfficeSignInManager( + BackOfficeUserManager userManager, + IHttpContextAccessor contextAccessor, + IBackOfficeExternalLoginProviders externalLogins, + IUserClaimsPrincipalFactory claimsFactory, + IOptions optionsAccessor, + IOptions globalSettings, + ILogger> logger, + IAuthenticationSchemeProvider schemes, + IUserConfirmation confirmation, + IEventAggregator eventAggregator) + : this(userManager, contextAccessor, externalLogins, claimsFactory, optionsAccessor, globalSettings, logger, schemes, confirmation, eventAggregator,StaticServiceProvider.Instance.GetRequiredService>()) + { + + } + + [Obsolete("Use non-obsolete constructor. This is scheduled for removal in V14.")] public BackOfficeSignInManager( BackOfficeUserManager userManager, IHttpContextAccessor contextAccessor, @@ -56,7 +74,7 @@ public BackOfficeSignInManager( ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation) - : this(userManager, contextAccessor, externalLogins, claimsFactory, optionsAccessor, globalSettings, logger, schemes, confirmation, StaticServiceProvider.Instance.GetRequiredService()) + : this(userManager, contextAccessor, externalLogins, claimsFactory, optionsAccessor, globalSettings, logger, schemes, confirmation, StaticServiceProvider.Instance.GetRequiredService(),StaticServiceProvider.Instance.GetRequiredService>()) { } diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs index 8265f493e7b0..02b0409ed33f 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs @@ -11,11 +11,9 @@ using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Net; using Umbraco.Cms.Core.Routing; -using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Web.BackOffice.Controllers; -using Umbraco.Cms.Web.Common.Security; using Umbraco.Extensions; namespace Umbraco.Cms.Web.BackOffice.Security; @@ -223,20 +221,6 @@ public void Configure(CookieAuthenticationOptions options) Constants.Security.BackOfficeAuthenticationType, Constants.Security.BackOfficeAuthenticationType, backOfficeIdentity)); - - // Update the security stamp when sign-in is successful - var userManager = ctx.HttpContext.RequestServices.GetRequiredService(); - - // TODO: check if securitySettings.AllowConcurrentLogins is not allowed - if (ctx.Principal != null) - { - BackOfficeIdentityUser? user = userManager.GetUserAsync(ctx.Principal).GetAwaiter().GetResult(); - - if (user is not null) - { - userManager.UpdateSecurityStampAsync(user).GetAwaiter().GetResult(); - } - } } return Task.CompletedTask; diff --git a/src/Umbraco.Web.Common/Security/MemberSignInManager.cs b/src/Umbraco.Web.Common/Security/MemberSignInManager.cs index d402e5f8435a..7a1eb951a581 100644 --- a/src/Umbraco.Web.Common/Security/MemberSignInManager.cs +++ b/src/Umbraco.Web.Common/Security/MemberSignInManager.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Notifications; @@ -30,14 +31,42 @@ public MemberSignInManager( IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation, IMemberExternalLoginProviders memberExternalLoginProviders, - IEventAggregator eventAggregator) - : base(memberManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) + IEventAggregator eventAggregator, + IOptions securitySettings) + : base(memberManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation, securitySettings) { _memberExternalLoginProviders = memberExternalLoginProviders; _eventAggregator = eventAggregator; } - [Obsolete("Use ctor with all params")] + [Obsolete("Use non-obsolete constructor. This is scheduled for removal in V14.")] + public MemberSignInManager( + UserManager memberManager, + IHttpContextAccessor contextAccessor, + IUserClaimsPrincipalFactory claimsFactory, + IOptions optionsAccessor, + ILogger> logger, + IAuthenticationSchemeProvider schemes, + IUserConfirmation confirmation, + IMemberExternalLoginProviders memberExternalLoginProviders, + IEventAggregator eventAggregator) + : this( + memberManager, + contextAccessor, + claimsFactory, + optionsAccessor, + logger, + schemes, + confirmation, + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService>() + ) + { + + } + + [Obsolete("Use non-obsolete constructor. This is scheduled for removal in V14.")] public MemberSignInManager( UserManager memberManager, IHttpContextAccessor contextAccessor, diff --git a/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs b/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs index 8a94e7e51220..cf7f3e52c0e0 100644 --- a/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs +++ b/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs @@ -2,8 +2,11 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Security; using Umbraco.Extensions; @@ -16,12 +19,15 @@ namespace Umbraco.Cms.Web.Common.Security; public abstract class UmbracoSignInManager : SignInManager where TUser : UmbracoIdentityUser { + private SecuritySettings _securitySettings; + // borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs protected const string UmbracoSignInMgrLoginProviderKey = "LoginProvider"; // borrowed from https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs protected const string UmbracoSignInMgrXsrfKey = "XsrfId"; + [Obsolete("Use non-obsolete constructor. This is scheduled for removal in V14.")] public UmbracoSignInManager( UserManager userManager, IHttpContextAccessor contextAccessor, @@ -30,8 +36,22 @@ public UmbracoSignInManager( ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation) + : this(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation, StaticServiceProvider.Instance.GetRequiredService>()) + { + } + + public UmbracoSignInManager( + UserManager userManager, + IHttpContextAccessor contextAccessor, + IUserClaimsPrincipalFactory claimsFactory, + IOptions optionsAccessor, + ILogger> logger, + IAuthenticationSchemeProvider schemes, + IUserConfirmation confirmation, + IOptions securitySettingsOptions) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) { + _securitySettings = securitySettingsOptions.Value; } protected abstract string AuthenticationType { get; } @@ -47,7 +67,7 @@ public override async Task PasswordSignInAsync(TUser user, string { // override to handle logging/events SignInResult result = await base.PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure); - return await HandleSignIn(user, user.UserName, result); + return result; } /// @@ -338,8 +358,14 @@ protected virtual async Task HandleSignIn(TUser? user, string? use user.AccessFailedCount = 0; } + await UserManager.UpdateAsync(user); + if (_securitySettings.AllowConcurrentLogins is false) + { + await UserManager.UpdateSecurityStampAsync(user); + } + Logger.LogInformation("User: {UserName} logged in from IP address {IpAddress}", username, Context.Connection.RemoteIpAddress); } else if (result.IsLockedOut) diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs index a17f748f0ca7..f4c3169408d8 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs @@ -70,7 +70,9 @@ public MemberSignInManager CreateSut() Mock.Of(), Mock.Of>(), Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of>(x=>x.Value == new SecuritySettings()) + ); } private static Mock MockMemberManager() From 0d5bb0872e29193f8823010187b88e6d349625b7 Mon Sep 17 00:00:00 2001 From: Elitsa Date: Mon, 16 Oct 2023 15:19:17 +0200 Subject: [PATCH 7/8] Cleanup --- .../Security/BackOfficeSignInManager.cs | 27 ++++++++++++++++--- ...BackOfficeSecurityStampValidatorOptions.cs | 5 ++-- .../Security/ConfigureSecurityStampOptions.cs | 9 ++++--- .../Security/MemberSignInManager.cs | 4 +-- .../Security/UmbracoSignInManager.cs | 11 ++++++-- .../Security/MemberSignInManagerTests.cs | 3 +-- 6 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs index 79bccb6edb00..8af883135d31 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeSignInManager.cs @@ -58,9 +58,19 @@ public BackOfficeSignInManager( IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation, IEventAggregator eventAggregator) - : this(userManager, contextAccessor, externalLogins, claimsFactory, optionsAccessor, globalSettings, logger, schemes, confirmation, eventAggregator,StaticServiceProvider.Instance.GetRequiredService>()) + : this( + userManager, + contextAccessor, + externalLogins, + claimsFactory, + optionsAccessor, + globalSettings, + logger, + schemes, + confirmation, + eventAggregator, + StaticServiceProvider.Instance.GetRequiredService>()) { - } [Obsolete("Use non-obsolete constructor. This is scheduled for removal in V14.")] @@ -74,7 +84,18 @@ public BackOfficeSignInManager( ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation) - : this(userManager, contextAccessor, externalLogins, claimsFactory, optionsAccessor, globalSettings, logger, schemes, confirmation, StaticServiceProvider.Instance.GetRequiredService(),StaticServiceProvider.Instance.GetRequiredService>()) + : this( + userManager, + contextAccessor, + externalLogins, + claimsFactory, + optionsAccessor, + globalSettings, + logger, + schemes, + confirmation, + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService>()) { } diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs index dcfd02c008e8..f64fba6b1d7c 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs @@ -11,9 +11,10 @@ public class ConfigureBackOfficeSecurityStampValidatorOptions : IConfigureOption { private readonly SecuritySettings _securitySettings; - public ConfigureBackOfficeSecurityStampValidatorOptions(IOptionsMonitor securitySettings) - => _securitySettings = securitySettings.CurrentValue; + public ConfigureBackOfficeSecurityStampValidatorOptions(IOptions securitySettings) + => _securitySettings = securitySettings.Value; + /// public void Configure(BackOfficeSecurityStampValidatorOptions options) => ConfigureSecurityStampOptions.ConfigureOptions(options, _securitySettings); } diff --git a/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs b/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs index 6b5330a089ec..7fe812f9bf2a 100644 --- a/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs +++ b/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs @@ -12,8 +12,8 @@ public class ConfigureSecurityStampOptions : IConfigureOptions securitySettings) - => _securitySettings = securitySettings.CurrentValue; + public ConfigureSecurityStampOptions(IOptions securitySettings) + => _securitySettings = securitySettings.Value; [Obsolete("Use the overload accepting SecuritySettings instead. Scheduled for removal in v14.")] public static void ConfigureOptions(SecurityStampValidatorOptions options) @@ -30,9 +30,9 @@ public static void ConfigureOptions(SecurityStampValidatorOptions options, Secur // Adjust the security stamp validation interval to a shorter duration // when concurrent logins are not allowed and the duration has the default interval value // (currently defaults to 30 minutes), ensuring quicker re-validation. - if (!securitySettings.AllowConcurrentLogins && options.ValidationInterval == TimeSpan.FromMinutes(30)) + if (securitySettings.AllowConcurrentLogins is false && options.ValidationInterval == TimeSpan.FromMinutes(30)) { - options.ValidationInterval = TimeSpan.FromSeconds(5); + options.ValidationInterval = TimeSpan.FromSeconds(30); } // When refreshing the principal, ensure custom claims that @@ -53,6 +53,7 @@ public static void ConfigureOptions(SecurityStampValidatorOptions options, Secur }; } + /// public void Configure(SecurityStampValidatorOptions options) => ConfigureOptions(options, _securitySettings); } diff --git a/src/Umbraco.Web.Common/Security/MemberSignInManager.cs b/src/Umbraco.Web.Common/Security/MemberSignInManager.cs index 7a1eb951a581..9a8aaa72f499 100644 --- a/src/Umbraco.Web.Common/Security/MemberSignInManager.cs +++ b/src/Umbraco.Web.Common/Security/MemberSignInManager.cs @@ -60,10 +60,8 @@ public MemberSignInManager( confirmation, StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService>() - ) + StaticServiceProvider.Instance.GetRequiredService>()) { - } [Obsolete("Use non-obsolete constructor. This is scheduled for removal in V14.")] diff --git a/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs b/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs index cf7f3e52c0e0..84cbce6d8df6 100644 --- a/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs +++ b/src/Umbraco.Web.Common/Security/UmbracoSignInManager.cs @@ -36,7 +36,15 @@ public UmbracoSignInManager( ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation) - : this(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation, StaticServiceProvider.Instance.GetRequiredService>()) + : this( + userManager, + contextAccessor, + claimsFactory, + optionsAccessor, + logger, + schemes, + confirmation, + StaticServiceProvider.Instance.GetRequiredService>()) { } @@ -358,7 +366,6 @@ protected virtual async Task HandleSignIn(TUser? user, string? use user.AccessFailedCount = 0; } - await UserManager.UpdateAsync(user); if (_securitySettings.AllowConcurrentLogins is false) diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs index f4c3169408d8..5394de5fd7ae 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.Common/Security/MemberSignInManagerTests.cs @@ -71,8 +71,7 @@ public MemberSignInManager CreateSut() Mock.Of>(), Mock.Of(), Mock.Of(), - Mock.Of>(x=>x.Value == new SecuritySettings()) - ); + Mock.Of>(x => x.Value == new SecuritySettings())); } private static Mock MockMemberManager() From 3adacd0031fb1d20c1b6d0d50b156fa6b6fd9ae5 Mon Sep 17 00:00:00 2001 From: Elitsa Date: Tue, 17 Oct 2023 09:29:11 +0200 Subject: [PATCH 8/8] Adding empty ctors --- .../ConfigureBackOfficeSecurityStampValidatorOptions.cs | 7 +++++++ .../Security/ConfigureSecurityStampOptions.cs | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs index f64fba6b1d7c..fcb180170311 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeSecurityStampValidatorOptions.cs @@ -1,5 +1,7 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Web.Common.Security; namespace Umbraco.Cms.Web.BackOffice.Security; @@ -11,6 +13,11 @@ public class ConfigureBackOfficeSecurityStampValidatorOptions : IConfigureOption { private readonly SecuritySettings _securitySettings; + public ConfigureBackOfficeSecurityStampValidatorOptions() + : this(StaticServiceProvider.Instance.GetRequiredService>()) + { + } + public ConfigureBackOfficeSecurityStampValidatorOptions(IOptions securitySettings) => _securitySettings = securitySettings.Value; diff --git a/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs b/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs index 7fe812f9bf2a..71d644d489a2 100644 --- a/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs +++ b/src/Umbraco.Web.Common/Security/ConfigureSecurityStampOptions.cs @@ -12,6 +12,11 @@ public class ConfigureSecurityStampOptions : IConfigureOptions>()) + { + } + public ConfigureSecurityStampOptions(IOptions securitySettings) => _securitySettings = securitySettings.Value;