Data cached in custom middleware
See original GitHub issueI’m using ASP.NET Core 1.1.0 and EF Core 1.1.0. I extended the built-in JWT Bearer authentication with my own middleware, but data is being cached between calls. I have a feeling the DB context is being reused, but I’m not sure how to troubleshoot.
Specifically, I’m calling the token endpoint to invoke the middleware and get a new JWT. The user is returned, all is good. If I manually update the DB with SSMS then log in again, the old, outdated user information is returned. The DB is being hit both times and it’s returning the correct data (I verified with SQL Profiler), but EF is apparently ignoring the updated data in favor of what it already had.
I’m using standard DI with the token middleware, nothing special there. Relevant code is below.
Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyContext>(options =>
options.UseSqlServer(Environment.GetEnvironmentVariable("DEV_CONNECTIONSTRING")));
services.AddScoped<UserService>();
}
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
IApplicationLifetime appLifetime)
/* These options specify:
* - token endpoint
* - authentication scheme
* - JWT issuer
* - duration of JWT validity
* - duration of refresh token validity */
app.UseMiddleware<JwtProviderMiddleware>(new JwtProviderOptions(
"/api/users/token",
"Bearer",
"MyJwtIssuer",
Duration.FromMinutes(30),
Duration.FromDays(7)
));
}
Custom JWT provider middleware:
public class JwtProviderMiddleware
{
readonly RequestDelegate _next;
readonly JwtProviderOptions _options;
readonly UserService _userSvc;
public JwtProviderMiddleware(RequestDelegate next,
JwtProviderOptions options,
UserService userSvc)
{
_next = next;
_options = options;
_userSvc = userSvc;
}
public async Task Invoke(HttpContext context)
{
// parse request body for email address and password
// user is returned incorrectly here
var user = await _userSvc.GetByEmailAsync(email);
}
}
UserService
:
public class UserService
{
MyContext _context;
public UserService(MyContext context)
{
_context = context;
}
public async Task<User> GetByEmailAsync(string email)
{
return await _context.Users.FirstOrDefaultAsync(u => u.Email == email);
}
}
Further technical details
EF Core version: 1.1.0 Database Provider: Microsoft.EntityFrameworkCore.SqlServer Operating system: Windows 10 Education x64 IDE: VS 2015 Enterprise
Issue Analytics
- State:
- Created 7 years ago
- Comments:6 (3 by maintainers)
@tuespetre Shoot, good catch! I have a couple other functions in this middleware that are called by
Invoke()
, that’s why I was using a field. I altered them to accept aUserService
parameter and I’m passing the local variable now.Thanks again!
You should use a local variable instead of a field to store the user service, otherwise your code is not thread-safe: request A begins and sets the field, but before it gets to the last line, request B begins and overwrites the field. Now when A gets to the last line, it’s seeing the value written by request B.