Added notification when requires user 2fa, so implementors can use this to send emails etc.

This commit is contained in:
Bjarke Berg
2022-04-20 10:56:15 +02:00
parent 7e6e9c7431
commit 7becf76a02
3 changed files with 69 additions and 1 deletions

View File

@@ -0,0 +1,14 @@
using System;
namespace Umbraco.Cms.Core.Notifications
{
public class UserTwoFactorRequestedNotification : INotification
{
public UserTwoFactorRequestedNotification(Guid userKey)
{
UserKey = userKey;
}
public Guid UserKey { get; }
}
}

View File

@@ -84,5 +84,11 @@ namespace Umbraco.Extensions
});
}
public static IUser GetByKey(this IUserService userService, Guid key)
{
int id = BitConverter.ToInt32(key.ToByteArray(), 0);
return userService.GetUserById(id);
}
}
}

View File

@@ -6,10 +6,14 @@ using System.Threading.Tasks;
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.Events;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Cms.Web.Common.Security;
using Umbraco.Extensions;
@@ -24,6 +28,7 @@ namespace Umbraco.Cms.Web.BackOffice.Security
{
private readonly BackOfficeUserManager _userManager;
private readonly IBackOfficeExternalLoginProviders _externalLogins;
private readonly IEventAggregator _eventAggregator;
private readonly GlobalSettings _globalSettings;
protected override string AuthenticationType => Constants.Security.BackOfficeAuthenticationType;
@@ -43,14 +48,32 @@ namespace Umbraco.Cms.Web.BackOffice.Security
IOptions<GlobalSettings> globalSettings,
ILogger<SignInManager<BackOfficeIdentityUser>> logger,
IAuthenticationSchemeProvider schemes,
IUserConfirmation<BackOfficeIdentityUser> confirmation)
IUserConfirmation<BackOfficeIdentityUser> confirmation,
IEventAggregator eventAggregator)
: base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation)
{
_userManager = userManager;
_externalLogins = externalLogins;
_eventAggregator = eventAggregator;
_globalSettings = globalSettings.Value;
}
[Obsolete("Use ctor with all params")]
public BackOfficeSignInManager(
BackOfficeUserManager userManager,
IHttpContextAccessor contextAccessor,
IBackOfficeExternalLoginProviders externalLogins,
IUserClaimsPrincipalFactory<BackOfficeIdentityUser> claimsFactory,
IOptions<IdentityOptions> optionsAccessor,
IOptions<GlobalSettings> globalSettings,
ILogger<SignInManager<BackOfficeIdentityUser>> logger,
IAuthenticationSchemeProvider schemes,
IUserConfirmation<BackOfficeIdentityUser> confirmation)
: this(userManager, contextAccessor, externalLogins, claimsFactory, optionsAccessor, globalSettings, logger, schemes, confirmation, StaticServiceProvider.Instance.GetRequiredService<IEventAggregator>())
{
}
/// <summary>
/// Custom ExternalLoginSignInAsync overload for handling external sign in with auto-linking
/// </summary>
@@ -284,6 +307,31 @@ namespace Umbraco.Cms.Web.BackOffice.Security
}
}
protected override async Task<SignInResult> SignInOrTwoFactorAsync(BackOfficeIdentityUser user, bool isPersistent,
string loginProvider = null, bool bypassTwoFactor = false)
{
var result = await base.SignInOrTwoFactorAsync(user, isPersistent, loginProvider, bypassTwoFactor);
if (result.RequiresTwoFactor)
{
NotifyRequiresTwoFactor(user);
}
return result;
}
protected void NotifyRequiresTwoFactor(BackOfficeIdentityUser user) => Notify(user,
(currentUser) => new UserTwoFactorRequestedNotification(currentUser.Key)
);
private T Notify<T>(BackOfficeIdentityUser currentUser, Func<BackOfficeIdentityUser, T> createNotification) where T : INotification
{
var notification = createNotification(currentUser);
_eventAggregator.Publish(notification);
return notification;
}
private void LogFailedExternalLogin(ExternalLoginInfo loginInfo, BackOfficeIdentityUser user) =>
Logger.LogWarning("The AutoLinkOptions of the external authentication provider '{LoginProvider}' have refused the login based on the OnExternalLogin method. Affected user id: '{UserId}'", loginInfo.LoginProvider, user.Id);
}