I need to implement custom "authentication" for my company. I say that in quotes because the user technically gets authenticated before it hits the application and if so, the userId will exist in request headers.
What I need to do is figure out a way to query the database and get additional user information based on that Id, and set the HttpContext.User object so that it can be used easily within the application.
The route I am taking now involves using Cookie Authentication without ASP.NET Core Identity. I have combined that idea with custom middleware that will query the database for the user, populate Claims from the db fields, and use the context.SignInAsync to create the cookie. I place this middleware before app.UseAuthentication(). The problem is upon first request the .User object is not set, because it seems the SignIn method only creates the cookie but doesn't set the .User object. The Authentication middleware doesn't yet see the cookie because it does not exist on first request.
Could anyone provide any ideas? Maybe I'm going about it wrong, or this technique is fine but I'm missing what I need to make it work.
in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication("MyAuthenticationCookie")
.AddCookie("MyAuthenticationCookie");
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMyUserMiddleware();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
custom Middleware:
public class MyUserMiddleware
{
private readonly RequestDelegate _next;
public MyUserMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
// Sign in user if this auth cookie doesn't exist
if (context.Request.Cookies[".AspNetCore.MyAuthenticationCookie"] == null)
{
// Get user from db - not done
// Set claims from user object - put in dummy test name for now
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "TEST"),
};
var claimsIdentity = new ClaimsIdentity(claims, "MyAuthenticationCookie");
context.SignInAsync("MyAuthenticationCookie", new ClaimsPrincipal(claimsIdentity));
}
return this._next(context);
}
}
public static class MyUserMiddlewareExtensions
{
public static IApplicationBuilder UseMyUserMiddleware(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<MyUserMiddleware>();
}
}