diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs index 5afe312a6e..297e54cd69 100644 --- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs @@ -132,7 +132,7 @@ namespace Volo.Abp.Account.Web.Pages.Account true ); - await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = result.ToIdentitySecurityLogAction(), diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLogoutModel.cs b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLogoutModel.cs index b25b34799d..bec2ede369 100644 --- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLogoutModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLogoutModel.cs @@ -20,7 +20,7 @@ namespace Volo.Abp.Account.Web.Pages.Account public override async Task OnGetAsync() { - await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = IdentitySecurityLogActionConsts.Logout diff --git a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs index aa22882701..575853f410 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs @@ -6,10 +6,8 @@ using Volo.Abp.Account.Localization; using Volo.Abp.Account.Settings; using Volo.Abp.Account.Web.Areas.Account.Controllers.Models; using Volo.Abp.AspNetCore.Mvc; -using Volo.Abp.EventBus.Local; using Volo.Abp.Identity; using Volo.Abp.Identity.AspNetCore; -using Volo.Abp.SecurityLog; using Volo.Abp.Settings; using Volo.Abp.Validation; using SignInResult = Microsoft.AspNetCore.Identity.SignInResult; @@ -28,22 +26,20 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers protected SignInManager SignInManager { get; } protected IdentityUserManager UserManager { get; } protected ISettingProvider SettingProvider { get; } - - protected ILocalEventBus LocalEventBus { get; } + protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } public AccountController( SignInManager signInManager, IdentityUserManager userManager, ISettingProvider settingProvider, - ISecurityLogManager securityLogManager, - ILocalEventBus localEventBus) + IdentitySecurityLogManager identitySecurityLogManager) { LocalizationResource = typeof(AccountResource); SignInManager = signInManager; UserManager = userManager; SettingProvider = settingProvider; - LocalEventBus = localEventBus; + IdentitySecurityLogManager = identitySecurityLogManager; } [HttpPost] @@ -62,7 +58,7 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers true ); - await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = signInResult.ToIdentitySecurityLogAction(), @@ -76,13 +72,13 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers [Route("logout")] public virtual async Task Logout() { - await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = IdentitySecurityLogActionConsts.Logout }); - await SignInManager.SignOutAsync(); + await SignInManager.SignOutAsync(); } [HttpPost] diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs index e645c9c9cf..7e79442bd7 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs @@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Volo.Abp.Account.Localization; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -using Volo.Abp.EventBus.Local; using Volo.Abp.Identity; using IdentityUser = Volo.Abp.Identity.IdentityUser; @@ -15,7 +14,7 @@ namespace Volo.Abp.Account.Web.Pages.Account { public SignInManager SignInManager { get; set; } public IdentityUserManager UserManager { get; set; } - public ILocalEventBus LocalEventBus { get; set; } + public IdentitySecurityLogManager IdentitySecurityLogManager { get; set; } protected AccountPageModel() { diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs index 05946182db..9d6c540ce5 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs @@ -98,7 +98,7 @@ namespace Volo.Abp.Account.Web.Pages.Account true ); - await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = result.ToIdentitySecurityLogAction(), @@ -194,7 +194,7 @@ namespace Volo.Abp.Account.Web.Pages.Account if (!result.Succeeded) { - await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, Action = "Login" + result @@ -224,7 +224,7 @@ namespace Volo.Abp.Account.Web.Pages.Account await SignInManager.SignInAsync(user, false); - await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, Action = result.ToIdentitySecurityLogAction(), diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs index fe7361e4ce..5923827a24 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Logout.cshtml.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.Account.Web.Pages.Account public virtual async Task OnGetAsync() { - await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = IdentitySecurityLogActionConsts.Logout diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogEvent.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogContext.cs similarity index 72% rename from modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogEvent.cs rename to modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogContext.cs index faac2d5033..42ec5e6fe5 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogEvent.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogContext.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; -using Volo.Abp.MultiTenancy; namespace Volo.Abp.Identity { - public class IdentitySecurityLogEvent : IMultiTenant + public class IdentitySecurityLogContext { public Guid? TenantId { get; set; } @@ -18,12 +17,12 @@ namespace Volo.Abp.Identity public Dictionary ExtraProperties { get; } - public IdentitySecurityLogEvent() + public IdentitySecurityLogContext() { ExtraProperties = new Dictionary(); } - public virtual IdentitySecurityLogEvent WithProperty(string key, object value) + public virtual IdentitySecurityLogContext WithProperty(string key, object value) { ExtraProperties[key] = value; return this; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogHandler.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogManager.cs similarity index 74% rename from modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogHandler.cs rename to modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogManager.cs index 5000d4d288..bdad21df13 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogHandler.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogManager.cs @@ -2,15 +2,13 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; using Volo.Abp.Security.Claims; using Volo.Abp.SecurityLog; -using Volo.Abp.Uow; using Volo.Abp.Users; namespace Volo.Abp.Identity { - public class IdentitySecurityLogHandler : ILocalEventHandler, ITransientDependency + public class IdentitySecurityLogManager : ITransientDependency { protected ISecurityLogManager SecurityLogManager { get; } protected IdentityUserManager UserManager { get; } @@ -18,7 +16,7 @@ namespace Volo.Abp.Identity protected IUserClaimsPrincipalFactory UserClaimsPrincipalFactory { get; } protected ICurrentUser CurrentUser { get; } - public IdentitySecurityLogHandler( + public IdentitySecurityLogManager( ISecurityLogManager securityLogManager, IdentityUserManager userManager, ICurrentPrincipalAccessor currentPrincipalAccessor, @@ -32,24 +30,24 @@ namespace Volo.Abp.Identity CurrentUser = currentUser; } - public async Task HandleEventAsync(IdentitySecurityLogEvent eventData) + public async Task SaveAsync(IdentitySecurityLogContext context) { Action securityLogAction = securityLog => { - securityLog.Identity = eventData.Identity; - securityLog.Action = eventData.Action; + securityLog.Identity = context.Identity; + securityLog.Action = context.Action; - if (securityLog.UserName.IsNullOrWhiteSpace()) + if (!context.UserName.IsNullOrWhiteSpace()) { - securityLog.UserName = eventData.UserName; + securityLog.UserName = context.UserName; } - if (securityLog.ClientId.IsNullOrWhiteSpace()) + if (!context.ClientId.IsNullOrWhiteSpace()) { - securityLog.ClientId = eventData.ClientId; + securityLog.ClientId = context.ClientId; } - foreach (var property in eventData.ExtraProperties) + foreach (var property in context.ExtraProperties) { securityLog.ExtraProperties[property.Key] = property.Value; } @@ -61,13 +59,13 @@ namespace Volo.Abp.Identity } else { - if (eventData.UserName.IsNullOrWhiteSpace()) + if (context.UserName.IsNullOrWhiteSpace()) { await SecurityLogManager.SaveAsync(securityLogAction); } else { - var user = await UserManager.FindByNameAsync(eventData.UserName); + var user = await UserManager.FindByNameAsync(context.UserName); if (user != null) { using (CurrentPrincipalAccessor.Change(await UserClaimsPrincipalFactory.CreateAsync(user))) diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogActionConsts.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogActionConsts.cs new file mode 100644 index 0000000000..47ad6b21d5 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogActionConsts.cs @@ -0,0 +1,19 @@ +namespace Volo.Abp.IdentityServer +{ + public class IdentityServerSecurityLogActionConsts + { + public static string LoginSucceeded { get; set; } = "LoginSucceeded"; + + public static string LoginLockedout { get; set; } = "LoginLockedout"; + + public static string LoginNotAllowed { get; set; } = "LoginNotAllowed"; + + public static string LoginRequiresTwoFactor { get; set; } = "LoginRequiresTwoFactor"; + + public static string LoginFailed { get; set; } = "LoginFailed"; + + public static string LoginInvalidUserName { get; set; } = "LoginInvalidUserName"; + + public static string LoginInvalidUserNameOrPassword { get; set; } = "LoginInvalidUserNameOrPassword"; + } +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogIdentityConsts.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogIdentityConsts.cs new file mode 100644 index 0000000000..4a5f96e0e2 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityServerSecurityLogIdentityConsts.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.IdentityServer +{ + public class IdentityServerSecurityLogIdentityConsts + { + public static string IdentityServer { get; set; } = "IdentityServer"; + } +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs index e45df9b3f7..90910e1894 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs @@ -10,6 +10,7 @@ using IdentityServer4.Validation; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; +using Volo.Abp.Identity; using Volo.Abp.IdentityServer.Localization; using Volo.Abp.Security.Claims; using Volo.Abp.Uow; @@ -23,18 +24,21 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity protected SignInManager SignInManager { get; } protected IEventService Events { get; } protected UserManager UserManager { get; } + protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } protected ILogger> Logger { get; } protected IStringLocalizer Localizer { get; } public AbpResourceOwnerPasswordValidator( UserManager userManager, SignInManager signInManager, + IdentitySecurityLogManager identitySecurityLogManager, IEventService events, - ILogger> logger, + ILogger> logger, IStringLocalizer localizer) { UserManager = userManager; SignInManager = signInManager; + IdentitySecurityLogManager = identitySecurityLogManager; Events = events; Logger = logger; Localizer = localizer; @@ -71,6 +75,12 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity additionalClaims.ToArray() ); + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() + { + Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer, + Action = result.ToIdentitySecurityLogAction(), + }); + return; } else if (result.IsLockedOut) @@ -91,12 +101,25 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity await Events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "invalid credentials", interactive: false)); errorDescription = Localizer["InvalidUserNameOrPassword"]; } + + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() + { + Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer, + Action = result.ToIdentitySecurityLogAction(), + UserName = context.UserName + }); } else { Logger.LogInformation("No user found matching username: {username}", context.UserName); await Events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "invalid username", interactive: false)); errorDescription = Localizer["InvalidUsername"]; + + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() + { + Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer, + Action = IdentityServerSecurityLogActionConsts.LoginInvalidUserName + }); } context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, errorDescription); diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/SignInResultExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/SignInResultExtensions.cs new file mode 100644 index 0000000000..6f167912c3 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/SignInResultExtensions.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.Identity; + +namespace Volo.Abp.IdentityServer.AspNetIdentity +{ + public static class SignInResultExtensions + { + public static string ToIdentitySecurityLogAction(this SignInResult result) + { + if (result.Succeeded) + { + return IdentityServerSecurityLogActionConsts.LoginSucceeded; + } + + if (result.IsLockedOut) + { + return IdentityServerSecurityLogActionConsts.LoginLockedout; + } + + if (result.RequiresTwoFactor) + { + return IdentityServerSecurityLogActionConsts.LoginRequiresTwoFactor; + } + + if (result.IsNotAllowed) + { + return IdentityServerSecurityLogActionConsts.LoginNotAllowed; + } + + if (!result.Succeeded) + { + return IdentityServerSecurityLogActionConsts.LoginFailed; + } + + return IdentityServerSecurityLogActionConsts.LoginFailed; + } + } +}