Skip to content

Commit

Permalink
Use IdentitySecurityLogManager instead EventBus to save security logs.
Browse files Browse the repository at this point in the history
  • Loading branch information
maliming committed Jul 20, 2020
1 parent 849f737 commit 83aeea2
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public override async Task<IActionResult> OnPostAsync(string action)
true
);

await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = result.ToIdentitySecurityLogAction(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public IdentityServerSupportedLogoutModel(IIdentityServerInteractionService inte

public override async Task<IActionResult> OnGetAsync()
{
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = IdentitySecurityLogActionConsts.Logout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
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;
Expand All @@ -28,22 +26,20 @@ public class AccountController : AbpController
protected SignInManager<IdentityUser> SignInManager { get; }
protected IdentityUserManager UserManager { get; }
protected ISettingProvider SettingProvider { get; }

protected ILocalEventBus LocalEventBus { get; }
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }

public AccountController(
SignInManager<IdentityUser> 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]
Expand All @@ -62,7 +58,7 @@ public virtual async Task<AbpLoginResult> Login(UserLoginInfo login)
true
);

await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = signInResult.ToIdentitySecurityLogAction(),
Expand All @@ -76,13 +72,13 @@ await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent
[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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
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;

Expand All @@ -15,7 +14,7 @@ public abstract class AccountPageModel : AbpPageModel
{
public SignInManager<IdentityUser> SignInManager { get; set; }
public IdentityUserManager UserManager { get; set; }
public ILocalEventBus LocalEventBus { get; set; }
public IdentitySecurityLogManager IdentitySecurityLogManager { get; set; }

protected AccountPageModel()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public virtual async Task<IActionResult> OnPostAsync(string action)
true
);

await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = result.ToIdentitySecurityLogAction(),
Expand Down Expand Up @@ -194,7 +194,7 @@ public virtual async Task<IActionResult> OnGetExternalLoginCallbackAsync(string

if (!result.Succeeded)
{
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
Action = "Login" + result
Expand Down Expand Up @@ -224,7 +224,7 @@ await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent

await SignInManager.SignInAsync(user, false);

await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
Action = result.ToIdentitySecurityLogAction(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class LogoutModel : AccountPageModel

public virtual async Task<IActionResult> OnGetAsync()
{
await LocalEventBus.PublishAsync(new IdentitySecurityLogEvent
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = IdentitySecurityLogActionConsts.Logout
Expand Down
Original file line number Diff line number Diff line change
@@ -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; }

Expand All @@ -18,12 +17,12 @@ public class IdentitySecurityLogEvent : IMultiTenant

public Dictionary<string, object> ExtraProperties { get; }

public IdentitySecurityLogEvent()
public IdentitySecurityLogContext()
{
ExtraProperties = new Dictionary<string, object>();
}

public virtual IdentitySecurityLogEvent WithProperty(string key, object value)
public virtual IdentitySecurityLogContext WithProperty(string key, object value)
{
ExtraProperties[key] = value;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@
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<IdentitySecurityLogEvent>, ITransientDependency
public class IdentitySecurityLogManager : ITransientDependency
{
protected ISecurityLogManager SecurityLogManager { get; }
protected IdentityUserManager UserManager { get; }
protected ICurrentPrincipalAccessor CurrentPrincipalAccessor { get; }
protected IUserClaimsPrincipalFactory<IdentityUser> UserClaimsPrincipalFactory { get; }
protected ICurrentUser CurrentUser { get; }

public IdentitySecurityLogHandler(
public IdentitySecurityLogManager(
ISecurityLogManager securityLogManager,
IdentityUserManager userManager,
ICurrentPrincipalAccessor currentPrincipalAccessor,
Expand All @@ -32,24 +30,24 @@ public IdentitySecurityLogHandler(
CurrentUser = currentUser;
}

public async Task HandleEventAsync(IdentitySecurityLogEvent eventData)
public async Task SaveAsync(IdentitySecurityLogContext context)
{
Action<SecurityLogInfo> 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;
}
Expand All @@ -61,13 +59,13 @@ public async Task HandleEventAsync(IdentitySecurityLogEvent eventData)
}
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)))
Expand Down
Original file line number Diff line number Diff line change
@@ -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";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer
{
public class IdentityServerSecurityLogIdentityConsts
{
public static string IdentityServer { get; set; } = "IdentityServer";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
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;
Expand All @@ -23,18 +24,21 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
protected SignInManager<IdentityUser> SignInManager { get; }
protected IEventService Events { get; }
protected UserManager<IdentityUser> UserManager { get; }
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
protected ILogger<ResourceOwnerPasswordValidator<IdentityUser>> Logger { get; }
protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; }

public AbpResourceOwnerPasswordValidator(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
IdentitySecurityLogManager identitySecurityLogManager,
IEventService events,
ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger,
ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger,
IStringLocalizer<AbpIdentityServerResource> localizer)
{
UserManager = userManager;
SignInManager = signInManager;
IdentitySecurityLogManager = identitySecurityLogManager;
Events = events;
Logger = logger;
Localizer = localizer;
Expand Down Expand Up @@ -71,6 +75,12 @@ public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext c
additionalClaims.ToArray()
);

await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
Action = result.ToIdentitySecurityLogAction(),
});

return;
}
else if (result.IsLockedOut)
Expand All @@ -91,12 +101,25 @@ public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext c
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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
}

0 comments on commit 83aeea2

Please sign in to comment.