16

I´m working on a ASP.NET Core Web API. I´m using the newest version 3.0.0-preview4.19216.2.

I have the problem, that my API-Controller ignores the Authorize-Attribute but on another controller the Attribute works fine.

 [Route("api/[controller]")] [ApiController] [Authorize(AuthenticationSchemes =JwtBearerDefaults.AuthenticationScheme)] public class SuppliersController : ControllerBase { [HttpGet("GetAll")] public IActionResult GetAll() { var companyId = int.Parse(User.Claims.FirstOrDefault(c => c.Type == "Company_Id").Value); // throws nullreference exception return Ok(); } } 

But on another controller I have something similar but there the attribute works as expected

 [Route("api/[controller]")] [ApiController] [Authorize] public class UsersController : ControllerBase { [HttpGet("{id}")] public IActionResult GetById(int id) { var test = User.Claims.FirstOrDefault(c => c.Type == "Company_Id").Value; } } 

In the user controller works everything fine.

I also tried it in the SupplierController without the

AuthenticationSchemes

but no different.

This is my AddAuthentication in the Startup.cs

services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(x => { x.Events = new JwtBearerEvents { OnTokenValidated = context => { var userService = context.HttpContext.RequestServices.GetRequiredService<IUserService>(); var userId = int.Parse(context.Principal.Identity.Name); var user = userService.GetById(userId); if (user == null) { // return unauthorized if user no longer exists context.Fail("Unauthorized"); } return Task.CompletedTask; }, OnAuthenticationFailed = context => { Console.WriteLine(context); return Task.CompletedTask; }, OnMessageReceived = context => { return Task.CompletedTask; } }; x.RequireHttpsMetadata = false; x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(key), ValidateIssuer = false, ValidateAudience = false }; }); 

here is my complete startup.cs

 public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { var appSettingsSection = Configuration.GetSection("AppSettings"); services.Configure<AppSettings>(appSettingsSection); AuthenticationService.ConfigureSchoolProjectAuthentication(services, appSettingsSection); DependencyInjectionService.Inject(services); services.AddMvcCore() .AddNewtonsoftJson(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.UseAuthentication(); app.UseRouting(); app.UseEndpoints(routes => { routes.MapControllers(); }); } } 

The strange thing is, when my SupplierController is called my authorization logic is not called (checked it with debugger) and when I call my UserController the logic is executed.

I think this is the reason why the claim is null. But why is the logic not called when the controller have a authorization attribute?

It´s seem like my authentication doesn't work entirely because I can access all my controller simply by using no authentication in Postman. What I´m doing wrong here?

2 Answers 2

29

Ok I found the anwser in this blog post ASP.NET Core updates in .NET Core 3.0 Preview 4

I have to change the order of my authentication registration from

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseHttpsRedirection(); app.UseAuthorization(); app.UseAuthentication(); app.UseRouting(); app.UseEndpoints(routes => { routes.MapControllers(); }); } 

to

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(routes => { routes.MapControllers(); }); } 

So this solve my problem.

Sign up to request clarification or add additional context in comments.

3 Comments

there is one issue left. you should switch: app.UseAuthentication(); app.UseAuthorization(); because first it should Authenticate and then gets Authorized. Otherwise you get always an 401 because he cannot Authorize when there was no Authentication
@Vampirasu thx for the response. I will test it because at the moment everything works fine. But again thx for the hint!
@Vampirasu sorry for the late response. I correct the misstake. Thank you for pointing it out!
1

For anyone else that finds their way here and hasn't thought slightly outside the box, check the namespace of your [Authorize] attribute and check that it corresponds to your expected namespace. In my case it should have been:

Microsoft.AspNetCore.Authorization 

But actually I'd been lazy and used namespace autocomplete and it had applied an unrelated attribute (which still worked at both a class and method level) from HotChocolate's Namespace.

Look out for this!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.