Open Closed

How Can I add user Id in AbpSecurityLogs table? #6118


User avatar
0
Priyanka created

In my application, in case of Logout, userId inserted automatically but username is not updating and in case of LoginSucceeded User id is not updating (it is external login), I want to add userid in AbpSecurityLogs if LoginSucceeded. I'm able to set the username but not userId Provide us with the following info:

  • ABP Framework version: v5.3.2
  • UI Type:React
  • Database System: EF Core (SQL Server)
  • Tiered (for MVC) or Auth Server Separated (for Angular): yes
  • Exception message and full stack trace:NA
  • Steps to reproduce the issue: Login and Logout and check the data in AbpSecurityLogs table

await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() { Identity = IdentitySecurityLogIdentityConsts.Identity, Action = Microsoft.AspNetCore.Identity.SignInResult.Success.ToIdentitySecurityLogAction(), UserName = user.Name });

we are using this to add UserName but here UserId is not present.


21 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    The UserId and UserName come from the ICurrentUser.

    You can change the current Principal to override the ICurrentUser.

    https://github.com/abpframework/abp/blob/dev/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySecurityLogManager.cs#L68-L75

  • User Avatar
    0
    Priyanka created

    Could you please help with an example, how can I change the current Principal to override the ICurrentUser ?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please share your code of IdentitySecurityLogManager

  • User Avatar
    0
    Priyanka created
    using System;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Identity;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Security.Claims;
    using Volo.Abp.SecurityLog;
    using Volo.Abp.Users;
    
    namespace Volo.Abp.Identity;
    
    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 IdentitySecurityLogManager(
            ISecurityLogManager securityLogManager,
            IdentityUserManager userManager,
            ICurrentPrincipalAccessor currentPrincipalAccessor,
            IUserClaimsPrincipalFactory<IdentityUser> userClaimsPrincipalFactory,
            ICurrentUser currentUser)
        {
            SecurityLogManager = securityLogManager;
            UserManager = userManager;
            CurrentPrincipalAccessor = currentPrincipalAccessor;
            UserClaimsPrincipalFactory = userClaimsPrincipalFactory;
            CurrentUser = currentUser;
        }
    
        public async Task SaveAsync(IdentitySecurityLogContext context)
        {
            Action<SecurityLogInfo> securityLogAction = securityLog =>
            {
                securityLog.Identity = context.Identity;
                securityLog.Action = context.Action;
    
                if (!context.UserName.IsNullOrWhiteSpace())
                {
                    securityLog.UserName = context.UserName;
                }
    
                if (!context.ClientId.IsNullOrWhiteSpace())
                {
                    securityLog.ClientId = context.ClientId;
                }
    
                foreach (var property in context.ExtraProperties)
                {
                    securityLog.ExtraProperties[property.Key] = property.Value;
                }
            };
    
            if (CurrentUser.IsAuthenticated)
            {
                await SecurityLogManager.SaveAsync(securityLogAction);
            }
            else
            {
                if (context.UserName.IsNullOrWhiteSpace())
                {
                    await SecurityLogManager.SaveAsync(securityLogAction);
                }
                else
                {
                    var user = await UserManager.FindByNameAsync(context.UserName);
                    if (user != null)
                    {
                        using (CurrentPrincipalAccessor.Change(await UserClaimsPrincipalFactory.CreateAsync(user)))
                        {
                            await SecurityLogManager.SaveAsync(securityLogAction);
                        }
                    }
                    else
                    {
                        await SecurityLogManager.SaveAsync(securityLogAction);
                    }
                }
            }
        }
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I mean your code instead of IdentitySecurityLogManager source code.

    we are using this to add UserName but here UserId is not present.

    Where did you call the below code? Please share the code. Thanks

    await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
    {
    Identity = IdentitySecurityLogIdentityConsts.Identity,
    Action = Microsoft.AspNetCore.Identity.SignInResult.Success.ToIdentitySecurityLogAction(),
    UserName = user.Name
    });
    
    
  • User Avatar
    0
    Priyanka created
    public override async Task<IActionResult> OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null)
    {
       IConfigurationRoot _config = new ConfigurationBuilder().SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
      .AddJsonFile("appsettings.json", false).Build();
      string webBaseUri = _config.GetSection("WebUISetting:URL").Get<string>();
      if (remoteError != null)
      {
          Logger.LogWarning($"External login callback error: {remoteError}");
          return RedirectToPage("./Login");
      }
    
      await IdentityOptions.SetAsync();
    
      var loginInfo = await SignInManager.GetExternalLoginInfoAsync();
      if (loginInfo == null)
      {
          Logger.LogWarning("External login info is not available");
          return RedirectToPage("./Login");
      } 
    
      var userName = loginInfo.Principal.FindFirstValue(ClaimTypes.Name);
    
      var result = await SignInManager.ExternalLoginSignInAsync(
          loginInfo.LoginProvider,
          userName,
          isPersistent: false,
          bypassTwoFactor: true
      );
    
      if (!result.Succeeded)
      {
          **await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
          {
              Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
              Action = "Login" + result
          });**
      }
    
      var user = await UserManager.FindByNameAsync(userName);
      if (result.Succeeded && user != null)
      {
          var activeUserOrganizationUnitMappings = await _userOrganizationUnitExt_TRRepository.GetListAsync(x => x.UserId == user.Id && x.IsActive);
          if (user.IsActive && activeUserOrganizationUnitMappings != null && activeUserOrganizationUnitMappings.Any())
          {
              user.SetProperty(CommonConsts.ConCurrentUserId, new Guid().ToString("N"));
              await UserManager.UpdateAsync(user);
              await SignInManager.SignInAsync(user, false);
    
             await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
              {
                  Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
                  Action = result.ToIdentitySecurityLogAction(),
                  UserName = user.Name
              });
    
              return RedirectSafely(returnUrl, returnUrlHash);
          }
          
      }
      
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    var userPrincipal = await SignInManager.CreateUserPrincipalAsync(user);
    using (CurrentPrincipalAccessor.Change(userPrincipal))
    {
           await IdentitySecurityLogManager.SaveAsync()
    }
    
  • User Avatar
    0
    Priyanka created

    hi

    var userPrincipal = await SignInManager.CreateUserPrincipalAsync(user); 
    using (CurrentPrincipalAccessor.Change(userPrincipal)) 
    { 
           await IdentitySecurityLogManager.SaveAsync() 
    } 
    

    SaveAsysc required to pass IdentitySecurityLogContext and in IdentitySecurityLogContext object only I'm not getting userId property, how userPrincipal is useful here ?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi

    Add your code into CurrentPrincipalAccessor' changescope.

    var userPrincipal = await SignInManager.CreateUserPrincipalAsync(user); 
    using (CurrentPrincipalAccessor.Change(userPrincipal)) 
    { 
          await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
          {
              Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
              Action = "Login" + result
          });
    } 
    
    var userPrincipal = await SignInManager.CreateUserPrincipalAsync(user); 
    using (CurrentPrincipalAccessor.Change(userPrincipal)) 
    { 
           await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
          {
                  Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
                  Action = result.ToIdentitySecurityLogAction(),
                  UserName = user.Name
          });
    } 
    
  • User Avatar
    0
    Priyanka created

    Hi

    Add your code into CurrentPrincipalAccessor' changescope.

    var userPrincipal = await SignInManager.CreateUserPrincipalAsync(user);  
    using (CurrentPrincipalAccessor.Change(userPrincipal))  
    {  
          await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() 
          { 
              Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, 
              Action = "Login" + result 
          }); 
    }  
    
    var userPrincipal = await SignInManager.CreateUserPrincipalAsync(user);  
    using (CurrentPrincipalAccessor.Change(userPrincipal))  
    {  
           await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext() 
          { 
                  Identity = IdentitySecurityLogIdentityConsts.IdentityExternal, 
                  Action = result.ToIdentitySecurityLogAction(), 
                  UserName = user.Name 
          }); 
    }  
    

    thanks, it is working, but how can we do the same in logout as on logout userId is updated but username is null.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please share the code of yourlogout code, Thanks

  • User Avatar
    0
    Priyanka created

    hi

    Please share the code of yourlogout code, Thanks

    we are calling this method, first we are calling external logout URL.

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(LoggedOutModel))]
    public class CustomLogout: LoggedOutModel
    {
       
        public override Task&lt;IActionResult&gt; OnGetAsync()
        {
            IConfigurationRoot _config = new ConfigurationBuilder().SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
                 .AddJsonFile("appsettings.json", false).Build();
            var externalLogout = _config.GetSection("ADFSConfig:EndSession").Get&lt;string&gt;();
            Response.Redirect(externalLogout);
            return base.OnGetAsync();
        }
         
    }
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    We have output the log on LogoutModel. Why you are overriding the LoggedOutModel?

  • User Avatar
    0
    Priyanka created

    hi

    We have output the log on LogoutModel. Why you are overriding the LoggedOutModel?

    I'm overriding as before logout, I need to call ADFS logout as well so first I'm redirecting to logout from third party than calling ABP's logout. With ABP's method, I am able to save the userid and action in my log table but username is not updating.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can't get user info in the LoggedOutModel class. so you can't output a username to security logs.

  • User Avatar
    0
    Priyanka created

    hi

    You can't get user info in the LoggedOutModel class. so you can't output a username to security logs.

    so, can we say that it's not possible to update username in log table for logout action?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Yes, you can't do that in the LoggedOutModel class

  • User Avatar
    0
    Priyanka created

    Yes, you can do that in the LoggedOutModel class

    If we can, then could you please help how can we?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    sorry, you can't do that in the LoggedOutModel class

  • User Avatar
    0
    Priyanka created

    sorry, you can't do that in the LoggedOutModel class

    Ok, thanks for your support.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    No problem

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11