Search code examples
c#asp.netasp.net-coreentity-framework-coreasp.net-identity-3

Asp.Net 5 / Identity 3: Caching of Claims in the IdentityDbContext implementation


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?


Solution

  • 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.