JWT Authorization in .NET 5 MVC Application

Viewed 603

I want to know how I can handle authorization using jwt for my MVC controllers in the .net 5 web app. The token generating functions are already written and it works perfectly in postman (bypassing bearer token), but a trivial redirect from the controller to another one with [Authorize] attribute doesn't work - 401 response. I checked the details of the request and the authorization header seems to be missing. Should I create my own middleware to refill authorization header in every request/redirect to other MVC controller or jwt framework for .net do it for me by passing a few rules in e.g Startup class? how it should work?

HomeController (main page)

    [HttpGet]
        public IActionResult Redirect()
        {
            var token = new JWTService().GenerateToken("test").Token;
            return Redirect("~/Person");
        }

PersonController

 [Authorize(AuthenticationSchemes  = JwtBearerDefaults.AuthenticationScheme)]
        public IActionResult Index()
        {
            return View();
        }
 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)
        {
            services.AddControllersWithViews();
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidAudience = "aaaa",
                    ValidIssuer = "aaaa",
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
                };
            });

        }

        // 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
            {
                app.UseExceptionHandler("/Home/Error");
                // 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.UseRouting();
            app.UseStaticFiles();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseCookiePolicy();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
1 Answers

You use AddJwtBearer to secure APIs and typically you provide the JWT access token using the authorization header in the incoming request and AddJwtBearer will convert the token to a User instance.

This code makes no sense:

    [HttpGet]
    public IActionResult Redirect()
    {
        var token = new JWTService().GenerateToken("test").Token;
        return Redirect("~/Person");
    }

Because you can't include the necessary token in the authorization response header through an redirect. The Redirect is for humans visiting your web site and not for API access.

So I think you are mixing up what the browser/users can do, and what API-access means.

I would first create one ASP.NET core service for humans to visit and then a separate service instance for the API, that the first service can send requests to.

Also, AddJwtBearer will typically not accept any tokens genererated by yourself, instead you should have an authorization service (like IdentityServer), issuing the tokens for you.

Related