Description
I am trying to set up authentication and authorization but I am seeing unexpected behavior.
I am running an ASPNET Core 2.0 app on windows (tried this on windows 10 and in a docker container with the following image 2.0.6-sdk-2.1.104-nanoserver-sac2016) and I have my authentication and authorization set up like this:
using Nuget package: Microsoft.AspNetCore.All 2.0.0 and also tried with 2.0.6
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("Test", policy =>
{
policy.Requirements.Add(new TestRequirement());
});
});
services.AddSingleton<IAuthorizationHandler, TestAuthorizationHandler>();
services.AddMvc();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer();
services.AddSingleton<IConfigureOptions<JwtBearerOptions>>(sp =>
{
return new ConfigureNamedOptions<JwtBearerOptions>(
JwtBearerDefaults.AuthenticationScheme,
options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
RequireSignedTokens = true,
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
IssuerSigningKey = rsaSecurityKey
};
});
});
}
public void Configure(IServiceProvider sp, IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
app.UseAuthentication();
app.UseMvc();
}
My requirement is empty and this is my authorization handler:
public class TestAuthorizationHandler : AuthorizationHandler<TestRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
TestRequirement requirement)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
}
My Controller get method:
[Authorize(Policy = "Test")]
[HttpGet]
[Route("Data")]
public async Task<string> GetDataAsync()
{
return await Task.FromResult("data");
}
The unexpected behavior:
Authentication is always ignored for that controller method, my authorization handler and controller are always reached, even if I don't supply an Authentication header or supply an invalid token.
Expected behavior:
Authorization should use the supplied default scheme in AddAuthentication to challenge the Authentication and not allow these calls through unless Authentication was successful.
Workaround:
Add the default scheme directly to the policy and require the user to be authenticated
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
When these are added I see the behavior I expect.
Am I misunderstanding the expected flow? Is this the expected behavior and RequireAuthenticatedUser is needed explicitly to block unauthenticated requests to go through authorization?