Home > Software design >  Not Found for actions with Authorize attribute while using identity in asp.net core
Not Found for actions with Authorize attribute while using identity in asp.net core

Time:11-10

As I mentioned in the title when I add Identity to my ASP.Net Core Web API project I get a NotFound error for actions that have Authorize attribute on top of it.
I checked this question but still I don't know where am I doing wrong.

I created this controller for simplicity:

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
    [Authorize(Roles = "test")]
    public ActionResult<string> Get(string name)
    {
        return Ok($"Hello {name}");
    }
}

And this is my code in Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
    {
        options.UseSqlServer(Configuration.GetConnectionString("SqlServer"));
    });
    services.AddControllers();

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        var secretKey = Encoding.UTF8.GetBytes(settings.SecretKey);
        var encriptionKey = Encoding.UTF8.GetBytes(settings.EncriptKey);

        options.TokenValidationParameters = new TokenValidationParameters()
        {
            ClockSkew = TimeSpan.FromMinutes(settings.ClockSkewMinutes),
            IssuerSigningKey = new SymmetricSecurityKey(secretKey),
            TokenDecryptionKey = new SymmetricSecurityKey(encriptionKey),
            // some other options
        };

        options.IncludeErrorDetails = false;
        options.RequireHttpsMetadata = true;
        options.SaveToken = true;
    });

    /* When I remove this code then it works */
    services.AddIdentity<User, Role>(options =>
    {
        // options
    }).AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...

    app.UseRouting();
    app.UseHttpsRedirection();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

More info:

  • When I remove the Role property from the Authorize attribute above the action, then it works
  • When I remove AddIdentity, it works.

CodePudding user response:

There are two reasons for this problem, at least I know 2 of them:


not defining DefaultChallengeScheme

Using

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).
         .AddJwtBearer

instead of using

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; // < this is the key
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer

You have to define the DefaultChallengeScheme property which is used as the default scheme by IAuthenticationService.ChallengeAsync()

Challenge the specified authentication scheme. An authentication challenge can be issued when an unauthenticated user requests an endpoint that requires authentication.


Adding order

(Your mistake) Order of adding services is important. Here you are adding JWT first then adding Identity, which overrides the settings that you did in JWT. You can just add JWT at the end.

----------------------------------------------------------------------

And to override the default settings for an action you can use

[Authorize(Roles = "admin", AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

or

[Authorize(Roles = "admin", AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
  • Related