Add settings to bypass 2fa for external logins (#11959)

* Added settings for bypassing 2fa for external logins

* Fixed issue with saving roles using member ID before the member had an ID.

* Added missing extension method

* Removed test classes from git

* rollback csproj
This commit is contained in:
Bjarke Berg
2022-02-09 10:19:39 +01:00
committed by GitHub
parent 927ee44efe
commit 3d28552a77
6 changed files with 88 additions and 4 deletions

View File

@@ -11,6 +11,8 @@ namespace Umbraco.Cms.Core.Configuration.Models
[UmbracoOptions(Constants.Configuration.ConfigSecurity)]
public class SecuritySettings
{
internal const bool StaticMemberBypassTwoFactorForExternalLogins = true;
internal const bool StaticUserBypassTwoFactorForExternalLogins = true;
internal const bool StaticKeepUserLoggedIn = false;
internal const bool StaticHideDisabledUsersInBackOffice = false;
internal const bool StaticAllowPasswordReset = true;
@@ -66,5 +68,17 @@ namespace Umbraco.Cms.Core.Configuration.Models
/// Gets or sets a value for the member password settings.
/// </summary>
public MemberPasswordConfigurationSettings MemberPassword { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to bypass the two factor requirement in Umbraco when using external login for members. Thereby rely on the External login and potential 2FA at that provider.
/// </summary>
[DefaultValue(StaticMemberBypassTwoFactorForExternalLogins)]
public bool MemberBypassTwoFactorForExternalLogins { get; set; } = StaticMemberBypassTwoFactorForExternalLogins;
/// <summary>
/// Gets or sets a value indicating whether to bypass the two factor requirement in Umbraco when using external login for users. Thereby rely on the External login and potential 2FA at that provider.
/// </summary>
[DefaultValue(StaticUserBypassTwoFactorForExternalLogins)]
public bool UserBypassTwoFactorForExternalLogins { get; set; } = StaticUserBypassTwoFactorForExternalLogins;
}
}

View File

@@ -112,6 +112,9 @@ namespace Umbraco.Cms.Core.Security
// create the member
_memberService.Save(memberEntity);
//We need to add roles now that the member has an Id. It do not work implicit in UpdateMemberProperties
_memberService.AssignRoles(new[] { memberEntity.Id }, user.Roles.Select(x => x.RoleId).ToArray());
if (!memberEntity.HasIdentity)
{
throw new DataException("Could not create the member, check logs for details");

View File

@@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
@@ -31,6 +32,7 @@ using Umbraco.Cms.Web.Common.ActionsResults;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Cms.Web.Common.Controllers;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Cms.Web.Common.Filters;
using Umbraco.Extensions;
using Constants = Umbraco.Cms.Core.Constants;
@@ -68,7 +70,10 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
private readonly IBackOfficeTwoFactorOptions _backOfficeTwoFactorOptions;
private readonly IManifestParser _manifestParser;
private readonly ServerVariablesParser _serverVariables;
private readonly IOptions<SecuritySettings> _securitySettings;
[ActivatorUtilitiesConstructor]
public BackOfficeController(
IBackOfficeUserManager userManager,
IRuntimeState runtimeState,
@@ -87,7 +92,8 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
IHttpContextAccessor httpContextAccessor,
IBackOfficeTwoFactorOptions backOfficeTwoFactorOptions,
IManifestParser manifestParser,
ServerVariablesParser serverVariables)
ServerVariablesParser serverVariables,
IOptions<SecuritySettings> securitySettings)
{
_userManager = userManager;
_runtimeState = runtimeState;
@@ -107,6 +113,51 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
_backOfficeTwoFactorOptions = backOfficeTwoFactorOptions;
_manifestParser = manifestParser;
_serverVariables = serverVariables;
_securitySettings = securitySettings;
}
[Obsolete("Use ctor with all params. This overload will be removed in Umbraco 10.")]
public BackOfficeController(
IBackOfficeUserManager userManager,
IRuntimeState runtimeState,
IRuntimeMinifier runtimeMinifier,
IOptions<GlobalSettings> globalSettings,
IHostingEnvironment hostingEnvironment,
ILocalizedTextService textService,
IGridConfig gridConfig,
BackOfficeServerVariables backOfficeServerVariables,
AppCaches appCaches,
IBackOfficeSignInManager signInManager,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
ILogger<BackOfficeController> logger,
IJsonSerializer jsonSerializer,
IBackOfficeExternalLoginProviders externalLogins,
IHttpContextAccessor httpContextAccessor,
IBackOfficeTwoFactorOptions backOfficeTwoFactorOptions,
IManifestParser manifestParser,
ServerVariablesParser serverVariables)
: this(userManager,
runtimeState,
runtimeMinifier,
globalSettings,
hostingEnvironment,
textService,
gridConfig,
backOfficeServerVariables,
appCaches,
signInManager,
backofficeSecurityAccessor,
logger,
jsonSerializer,
externalLogins,
httpContextAccessor,
backOfficeTwoFactorOptions,
manifestParser,
serverVariables,
StaticServiceProvider.Instance.GetRequiredService<IOptions<SecuritySettings>>()
)
{
}
[HttpGet]
@@ -458,7 +509,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
if (response == null) throw new ArgumentNullException(nameof(response));
// Sign in the user with this external login provider (which auto links, etc...)
SignInResult result = await _signInManager.ExternalLoginSignInAsync(loginInfo, isPersistent: false);
SignInResult result = await _signInManager.ExternalLoginSignInAsync(loginInfo, isPersistent: false, bypassTwoFactor: _securitySettings.Value.UserBypassTwoFactorForExternalLogins);
var errors = new List<string>();

View File

@@ -11,6 +11,7 @@ using Umbraco.Cms.Core.Net;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Security;
using Umbraco.Cms.Web.BackOffice.Security;
using Umbraco.Cms.Web.Common.AspNetCore;
using Umbraco.Cms.Web.Common.Security;
@@ -77,5 +78,14 @@ namespace Umbraco.Extensions
return umbracoBuilder;
}
public static BackOfficeIdentityBuilder AddTwoFactorProvider<T>(this BackOfficeIdentityBuilder identityBuilder, string providerName) where T : class, ITwoFactorProvider
{
identityBuilder.Services.AddSingleton<ITwoFactorProvider, T>();
identityBuilder.Services.AddSingleton<T>();
identityBuilder.AddTokenProvider<TwoFactorBackOfficeValidationProvider<T>>(providerName);
return identityBuilder;
}
}
}

View File

@@ -17,6 +17,7 @@
<ProjectReference Include="../Umbraco.Web.Website/Umbraco.Web.Website.csproj" />
<ProjectReference Include="../Umbraco.Persistence.SqlCe/Umbraco.Persistence.SqlCe.csproj" Condition="'$(OS)' == 'Windows_NT'" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Plugins" />

View File

@@ -8,7 +8,9 @@ using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Logging;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Routing;
@@ -29,6 +31,7 @@ namespace Umbraco.Cms.Web.Website.Controllers
{
private readonly IMemberManager _memberManager;
private readonly ITwoFactorLoginService _twoFactorLoginService;
private readonly IOptions<SecuritySettings> _securitySettings;
private readonly ILogger<UmbExternalLoginController> _logger;
private readonly IMemberSignInManagerExternalLogins _memberSignInManager;
@@ -42,7 +45,8 @@ namespace Umbraco.Cms.Web.Website.Controllers
IPublishedUrlProvider publishedUrlProvider,
IMemberSignInManagerExternalLogins memberSignInManager,
IMemberManager memberManager,
ITwoFactorLoginService twoFactorLoginService)
ITwoFactorLoginService twoFactorLoginService,
IOptions<SecuritySettings> securitySettings)
: base(
umbracoContextAccessor,
databaseFactory,
@@ -55,6 +59,7 @@ namespace Umbraco.Cms.Web.Website.Controllers
_memberSignInManager = memberSignInManager;
_memberManager = memberManager;
_twoFactorLoginService = twoFactorLoginService;
_securitySettings = securitySettings;
}
/// <summary>
@@ -95,7 +100,7 @@ namespace Umbraco.Cms.Web.Website.Controllers
}
else
{
SignInResult result = await _memberSignInManager.ExternalLoginSignInAsync(loginInfo, false);
SignInResult result = await _memberSignInManager.ExternalLoginSignInAsync(loginInfo, false, _securitySettings.Value.MemberBypassTwoFactorForExternalLogins);
if (result == SignInResult.Success)
{