user2058413
user2058413

Reputation: 795

Asp.Net Core configure Identity authentication middleware properly

Requirement is that I have MVC & WebAPI in the project. MVC views will be delivered for initial rendering like Login, base views of features (ex:- Users/Index, Dashboard/Index etc..) Web APIs will be used for other work within these views via AJAX with JWT.

I am using Asp.Net core Identity for user management related work running on .Net 5.0

I am confused with configuring multiple identity schemes and the proper configuration of authentication/authorization pipeline in conigureservices() & configure() in startup.

  1. To configure multiple auth schemes I referred to https://stackoverflow.com/a/64887479/2058413 since it's done using same versions that I use. So my startup methods are below which is similar to the code in that thread.

         public void ConfigureServices(IServiceCollection services)
         {
             string connectionString = Configuration.GetConnectionString("default");
             services.AddDbContext<AppDBContext>(c => c.UseSqlServer(connectionString));
    
             services.AddIdentity<IdentityUser, IdentityRole>()
                 .AddEntityFrameworkStores<AppDBContext>();
    
             services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                 .AddCookie(x =>
                 {
                     x.LoginPath = "/Account/Login";
                     x.ExpireTimeSpan = TimeSpan.FromMinutes(10d);
                     x.AccessDeniedPath = "/Account/Register";
                 })
                 .AddJwtBearer(x =>
                 {
                     x.RequireHttpsMetadata = false;
                     x.SaveToken = true;
                     x.TokenValidationParameters = new TokenValidationParameters
                     {
                         ValidateIssuerSigningKey = true,
                         IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("123456")),
                         ValidateIssuer = false,
                         ValidateAudience = false
                     };
                 });
    
             services.AddAuthorization(options =>
             {
                 var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme);
                 defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
                 options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
             });
    
    
             services.AddControllersWithViews();
         }
    

    My App configure method is below

         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
         {
             if (env.IsDevelopment())
             {
                 app.UseDeveloperExceptionPage();
             }
             else
             {
                 app.UseExceptionHandler("/Home/Error");
             }
             app.UseStaticFiles();
    
             app.UseRouting();
    
             app.UseAuthentication();
    
             app.UseAuthorization();
    
             app.UseEndpoints(endpoints =>
             {
                 endpoints.MapControllerRoute(
                     name: "default",
                     pattern: "{controller=Home}/{action=Index}/{id?}");
             });
         }
    

Then the test method in controller(where user should get redirected to after authentication) is below

    [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
    public IActionResult Index()
    {
        return View();
    }

To my understanding the order of the pipeline configuration is correct. Now here are the problems I face.

  1. As specified in .AddCookie(option=>) , user doesn't get redirected to login page. However, if I remove the JwtBearerDefaults.AuthenticationScheme from the services.AddAuthorization(…) it gets redirected to login page properly. Why is that?

  2. So I remove JwtBearerDefaults.AuthenticationScheme; which takes me to login and after successful login I can see that HttpContext.User.Identity.IsAuthenticated is set to true. But it doesn't redirect to Home/Index. No errors thrown and in browser console [network tab] it shows a 302 and redirect back to login. Since I have added [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] to Index method in HomeController, I tried removing the scheme and adding [Authorize] and tried again. Still it gets redirected to login page. This is another thing I am confused about.

  3. So I removed everything related to dual scheme authentication and left the ConfigureService() with below code

             string connectionString = Configuration.GetConnectionString("default");
             services.AddDbContext<AppDBContext>(c => c.UseSqlServer(connectionString));
    
             services.AddIdentity<IdentityUser, IdentityRole>()
                 .AddEntityFrameworkStores<AppDBContext>();
             services.AddControllersWithViews();
    

    Now everything works fine (redirection to login if not authenticated and also redirects to /Home/Index after authorization).

    I went through below links as well about multi scheme authentication, but I am still confused with this pipeline configuration. ASP.NET Core WebAPI Cookie + JWT Authentication https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2 https://mitchelsellers.com/blog/article/using-multiple-authentication-authorization-providers-in-asp-net-core

    I need help only to this multi-scheme authentication pipeline configuration part.

Upvotes: 0

Views: 1378

Answers (1)

user2058413
user2058413

Reputation: 795

Ok, after some research the main issue was;

  1. I have mixed up old ways of registering services in StartUp (asp.net core 3.x). So had to clear up all those. Resources that helped me to do that;

Migrate from ASP.NET Core 3.1 to 5.0

ASP.NET Core Middleware

This cleaned up a lot of unnecessary code since in .Net 5 there were some shortcuts that could be used.

  1. Order of service registrations. This may depend on what kind of services you are using, but in my case the order was something like below:
  1. AddIdentity
  2. setup Cookie & JWT authentication c)
  3. My Multitenant stuff
  4. AddCors
  5. AddModules (will be option for some of you. I use it to load plugins dynamically)
  6. Other stuff (However, even in these places the order might matter depending on what you do)

The other thing was, I had to remove ConfigureApplicationCookie() since AddIdentity seems to be doing that. Also in AddAuthorization() earlier I had code to specify what are the default schemes i wanted to use (Cookie & JWT). But now I had to remove all that. Reason is Identity takes over the cookie scheme and when I specify below, JWTAuth takes over.

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] 

Generally setting up Startup properly seems to be tricky depending on different services you use. Order will matter

Upvotes: 0

Related Questions