Reputation: 1104
I'm attempting to implement a custom authorization policy in my asp.net core 2.0 application.
In my Custom AuthorizationHandler I have this check:
if (!context.User.Identity.IsAuthenticated)
{
this.logger.LogInformation("Failed to authorize user. User is not authenticated.");
return Task.CompletedTask;
}
// ... More authorization checks
which makes sense, as unauthenticated users are not authorized for my controller action.
I'm using JWT bearer auth and have it configured like this:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "<issuer>",
ValidAudience = "<audience>",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signingKey)),
ValidateLifetime = false
};
});
I'm also registering my authorization requirement and handler (note these registrations happen AFTER I've configured authentication above, and BEFORE I call serivces.AddMVC()
:
services.AddAuthorization(options =>
{
options.AddPolicy(Constants.AuthorizationPolicies.MyCustomPolicy,
policy => policy.Requirements.Add(new MyCustomRequirement()));
});
services.AddScoped<IAuthorizationHandler, MyCustomAuthorizationHandler>();
Here's my problem, It appears my Authorization Policy is executing before the jwt token is being challenged and validated, as a result, my authorization policy is failing because the user is not authenticated.
Here's a log of a sample call:
Now listening on: http://localhost:60235
Application started. Press Ctrl+C to shut down.
[14:50:57 INF] Request starting HTTP/1.1 GET http://localhost:60235/api/values application/json
[14:51:03 INF] Failed to authorize user. User is not authenticated.
[14:51:03 INF] Authorization failed for user: null.
[14:51:03 INF] Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
[14:51:03 INF] Executing ChallengeResult with authentication schemes ([]).
[14:51:03 INF] Successfully validated the token.
[14:51:03 INF] AuthenticationScheme: Bearer was challenged.
[14:51:03 INF] Executed action AuthorizationTestClient.Controllers.ValuesController.Get (AuthorizationTestClient) in 5819.1586ms
[14:51:03 INF] Request finished in 5961.5619ms 401
As you can see, the authorization policy executes first, fails because the user isn't authenticated and then the authentication challenge happens.
Shouldn't this be the other way around? How do I tell asp.net to perform authentication before authorization?
Upvotes: 4
Views: 5566
Reputation: 1104
Ok.. turns out it was very easy fix. I needed a call to app.UseAuthentication() in my Configure method. Silly me!
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
Upvotes: -14
Reputation: 31282
I'm also registering my authorization requirement and handler (note these registrations happen AFTER I've configured authentication above, and BEFORE I call serivces.AddMVC()
The order of services registration in DI container is not quite important. What is important it's the order of middleware registration in Startup.Configure
method. You have not provided the code of this method, but I bet you add authentication middleware after MVC middleware or don't add it at all. Authentication middleware should be added before MVC, so make sure your Startup.Configure
looks similar to this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
Check following articles for more details:
Upvotes: 12