I've spent the last few days toying with authentication for my service in ASP.NET Core. My app has a simple authentication token system. It is expected that the request has a cookie on it, I take that cookie and make a request to my auth server. The auth server gives me back the user's entitlements. If the cookie doesn't exist, or the auth request comes back with a failure, the app should spit out a 401. On a Success it will go to the next part of the pipeline and check authorization on the entitlements.
I set up my authentication middleware as one would expect - inheriting from the AuthenticationHandler, AuthenticationMiddleware, etc. My custom Authentication Handler inherits from Authenticationhandler and overwrites HandleAuthenticateAsync(). This method uses the user supplied cookie to get user data, create my ClaimsPrincipal, and either returns AuthenticateResult.Success or AuthenticateResult.Fail.
When AuthenticationResult.Fail returns, I figured the app would quit, but my app will still go to the next part of the pipeline (app.UseMvc()), when I thought it would return a 401 error.
My Startup.cs looks like follows.
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCustomAuthentication(new CustomAuthenticationOptions()
{
AutomaticChallenge = true,
AutomaticAuthenticate = true
});
app.UseMvc();
}
}
This will fail authentication, I'll see it in the output, but then UseMvc will still run. It isn't until I did this to services that it would quit, but with an authorization error rather than the authentication error that should have been flagged.
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
Is this how it is supposed to be set up? When authentication fails, shouldn't the pipeline shut down?