I am using IdentityServer 4 (with sql storage) for my asp.net core API. I would like to add a "Last Accessed" field somewhere in the database that can be used to order one of my user types in a user search endpoint. Ideally this would show the last time they performed an action in the system.
If I do this in the login method it won't be accurate as it will only update when a token is initially generated. I could add a method to every endpoint that the user accessed but this doesn't feel like the right solution as it would be repeating myself.
What is the correct place and method for maintaining a database field that records the last time a user accessed the system?
For recording the user active time, you could try Middleware which will be called for every request.
Here are steps.
1.Add field to ApplicationUser which is store the last accessed time
public class ApplicationUser : IdentityUser
{
public DateTime LastAccessed { get; set; }
}
2.run command add-migration LastAccessed and update-database
3.Add middleware to update the last accessed time based on the user name
app.UseAuthentication();
app.Use(async (context, next) => {
await next.Invoke();
//handle response
//you may also need to check the request path to check whether it requests image
if (context.User.Identity.IsAuthenticated)
{
var userName = context.User.Identity.Name;
//retrieve uer by userName
using (var dbContext = context.RequestServices.GetRequiredService<ApplicationDbContext>())
{
var user = dbContext.ApplicationUser.Where(u => u.UserName == userName).FirstOrDefault();
user.LastAccessed = DateTime.Now;
dbContext.Update(user);
dbContext.SaveChanges();
}
}
});
I added an answer for a similar question which I did with a centralized solution in the identity server
project (using IEventSink
). We have 30+ apis and I found it better to do the solution in only one place instead of doing it in each and every api. So i added this answer here just in case anybody came across and have the same requirements as mine. This is my answer