While looking for a way to be able to assign and revoke roles via an admin controller for users other than the one making a request, I've implemented a custom IAuthorizeFilter that checks if Guid tag, stored as a Claim, matches to a value in the Entity Framework 7 Code First Identity table for UserClaims.
Essentials, it's this code:
public class RefreshUserClaimsFilterAttribute : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext context)
{
var User = context.HttpContext.User;
var dbContext = context.HttpContext.ApplicationServices.GetRequiredService<ApplicationDbContext>();
var stampFromClaims = User.Claims.FirstOrDefault(Claim => Claim.Type == "ClaimsStamp")?.Value;
var stampFromDb = dbContext.UserClaims.Where(UserClaim => UserClaim.UserId == User.GetUserId()).ToList().FirstOrDefault(UserClaim => UserClaim.ClaimType == "ClaimsStamp")?.ClaimValue;
// Update claims via RefreshSignIn if necessary
}
}
I'm having the problem at the line where I'm assigning var stampFromDb
, it could be much more readable in the following way:
var stampFromDb = dbContext.UserClaims.FirstOrDefault(UserClaim => UserClaim.UserId == User.GetUserId() && UserClaim.ClaimType == "ClaimsStamp")?.ClaimValue;
That, however, gives me cached (the same values as the actual claims from User.Identity) results and I could not find any documentation on this. My best guess is that the error is somewhere on my side, but I've never encountered such a problem before. This is the first time I'm using Asp.Net 5 and EF7. I'm using the default connection (LocalDB) to SQL Server 12.0.2000.
Is this a feature and, if yes, can it be turned off or did I make a mistake somewhere?
The issue was caused due to there being two different ways to create a service via dependency injection: The sample code in my question used
var dbContext = context.HttpContext.ApplicationServices.GetRequiredService<ApplicationDbContext>();
where it should use
var dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
The difference here is between ApplicationServices
and RequestServices
. It looks like the ApplicationServices
injector does have an instance of the database context somewhere which has had the DbSet filled earlier and therefore returning cached data instead of doing a database query.