Search code examples
c#authentication.net-coreasp.net-core-identity

ASP.NET Core 3.1.1 Jwt redirects instead of returning http status 401 after migration from ASP.NET Core 2.2


After migrating my website from .NET Core 2.2 to 3.1.1, my api endpoints suddenly started trying to redirect my api request to a default login page (/Account/Login?ReturnUrl=, which I don't even have in any of my routes).

My api is using a JWT bearer authentication scheme, with JWT Challenge Scheme, but still the redirect happened.

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})

I finally found a solution to the problem, but I have no idea why it actually helped.

Initially I had my services set as:

services
  .AddIdentity<IdentityUser, IdentityRole>()
  .AddSignInManager()
  .AddEntityFrameworkStores<CleWebToolsIdentityDbContext>();

But that did the redirect.

What finally solved my problem was setting them to:

services
  .AddIdentityCore<IdentityUser>()
  .AddRoles<IdentityRole>()
  .AddSignInManager()
  .AddEntityFrameworkStores<CleWebToolsIdentityDbContext>();

Can somebody tell me what is going on here?

How does the AddIdentity-method cause the redirect, even though the challenge scheme should be JWT?


Solution

  • That is because AddIdentity registers the default Cookie-based authentication schemes for the application itself, external sign-in (e.g. Facebook and Google), and 2FA . It will reset the default schema if you put services.AddIdentity<IdentityUser, IdentityRole>() below the AddJwtBearer config , to avoid this , you can put the identity config above the jwt bearer config :

    services
    .AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders().AddDefaultUI();
    
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(options =>
    {
      ....
    
    });
    

    Use AddIdentityCore works because it won't registers the default Cookie-based authentication schemes , see AddIdentity vs AddIdentityCore for more details.