diff --git a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs index f4b4a2d35a..90b39e9953 100644 --- a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs @@ -1,4 +1,7 @@ -using System.Threading.Tasks; +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; @@ -120,4 +123,11 @@ public class AbpSignInManager : SignInManager { return await base.SignInOrTwoFactorAsync(user, isPersistent, loginProvider, bypassTwoFactor); } + + public override async Task SignInWithClaimsAsync(IdentityUser user, AuthenticationProperties authenticationProperties, IEnumerable additionalClaims) + { + user.SetLastSignInTime(DateTimeOffset.UtcNow); + await UserManager.UpdateAsync(user); + await base.SignInWithClaimsAsync(user, authenticationProperties, additionalClaims); + } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index bf81984ed5..3f4a91117c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -127,6 +127,11 @@ public class IdentityUser : FullAuditedAggregateRoot, IUser, IHasEntityVer /// public virtual DateTimeOffset? LastPasswordChangeTime { get; protected set; } + /// + /// Gets or sets the last sign-in time for the user. + /// + public virtual DateTimeOffset? LastSignInTime { get; protected set; } + //TODO: Can we make collections readonly collection, which will provide encapsulation. But... can work for all ORMs? /// @@ -409,6 +414,11 @@ public class IdentityUser : FullAuditedAggregateRoot, IUser, IHasEntityVer LastPasswordChangeTime = lastPasswordChangeTime; } + public virtual void SetLastSignInTime(DateTimeOffset? lastSignInTime) + { + LastSignInTime = lastSignInTime; + } + [CanBeNull] public virtual IdentityUserPasskey FindPasskey(byte[] credentialId) { diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs index 5059c7c5ca..07be60da44 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs @@ -405,6 +405,9 @@ public partial class TokenController } ); + user.SetLastSignInTime(DateTimeOffset.UtcNow); + await UserManager.UpdateAsync(user); + return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); }