8

I'm trying to implement JWT based authentication in my App that has an Angular 8 Frontend and .Net Core Backend. I have added

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

and

services.AddAuthentication(opt =>

in the startup class.I have decorated the controller method using the [Authorize] attribute. But when i try to hit the controller method without any tokens it allows entry into the controller method.

StartUp

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 jwtSettings = Configuration.GetSection("JwtSettings");
            services.AddAuthentication(opt =>
            {
                opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = jwtSettings.GetSection("validIssuer").Value,
                    ValidAudience = jwtSettings.GetSection("validAudience").Value,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.GetSection("securityKey").Value))
                };
            });
            services.AddSignalR();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            // In production, the Angular files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });

            // requires using Microsoft.Extensions.Options
            services.Configure<DatabaseSettings>(
                Configuration.GetSection(nameof(DatabaseSettings)));

            services.AddSingleton<IDatabaseSettings>(sp =>
                sp.GetRequiredService<IOptions<DatabaseSettings>>().Value);

            services.AddSingleton<FileService>();

            services.AddSingleton<InternalReportService>();


            services.AddTransient<MailService>();
            services.AddMvc(option => option.EnableEndpointRouting = false);


        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseRouting();
            app.UseMvc();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();          
            app.UseAuthentication();
            app.UseAuthorization();             

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<CoreHub>("/corehub");
                endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}");

            });

            app.UseSpa(spa =>
            {
                  
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");

                }
            });
        }
    }

Controller

[Authorize]
public async Task UploadFile(IFormFile file)
{
// Do Stuff
}
3
  • try use this services.AddMvcCore() instead of services.AddMvc() Commented Oct 6, 2021 at 18:39
  • You did not share code that creates the JWT or persists the token. Commented Oct 6, 2021 at 19:55
  • https://code-maze.com/authentication-aspnetcore-jwt-1/ Commented Oct 6, 2021 at 20:01

3 Answers 3

9
+25

Well, you have configured the authentication part of your API, now you need to configure the authorization the same way...

You can configure like this:

services.AddAuthorization(options =>
{
    options.AddPolicy("Default", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build());

    options.AddPolicy("Admin", new AuthorizationPolicyBuilder()
        .RequireRole("Admin")
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build());
});

Then you will be able to use the attribute as

[Authorize("User")]
[Authorize("Admin")]

on your controllers or specific endpoints.

If you wish to put this default policy on all your endpoints/controllers and control only the "AllowAnonymous" part of if, you can do this:

services.AddMvc()
        .AddMvcOptions(options =>
        {
            // Mark all endpoints with the default policy
            options.Filters.Add(new AuthorizeFilter("Default"));
        })
Sign up to request clarification or add additional context in comments.

4 Comments

Should be the correct answer.
Why is it mandatory to define roles? My application only needs valid Token to function,there is no need for roles.
You dont need a role, just define a default -no named- policy, as @GibbOne already showed using opts.DefaultPolicy = new AuthorizationPolicyBuilder(opts.DefaultPolicy).RequireAuthenticatedUser(), in fact you can use both if you want, the same is applied to the global filter
In fact, the default policy is static, just calling services.AddAuthorization() should work i guess, otherwise youll have to configure it
4

According to Your authentication scheme, You should specify attribute this way: [Authorize(AuthenticationSchemes = "Bearer")] and this should work as You expect

5 Comments

Thanks ... but this does not work.
@techno can you provide full code of your controller?
The issue is sorted.I was hitting the wrong method.
@techno Do You mean that some of answers was correct? Or You mean that whole question wasn't about problem?
Adding Bearer actually fixed the issue. But the real problem was something else.
1

I usually add DefaultSchema.

services.AddAuthentication(opt =>
{
    opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    opt.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
//...

and authorization.

services.AddAuthorization(opts =>
{
    opts.DefaultPolicy = new AuthorizationPolicyBuilder(opts.DefaultPolicy)
          .RequireAuthenticatedUser()
//...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.