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
}
Create Custom Authentication handler to validate JWT token Get the metadata from the custom authorization server (OAuth) Create .NET Core Project. Create "AuthConfigManager" class. It is used to get the metadata from the authorization server. Add below references to the project using the NuGet package manager.
The AddJwtBearer will handle all requests and will check for a valid JWT Token in the header. If it is not passed, or the token is expired, it will generate a 401 Unauthorized HTTP response. Next, I am going to implement the authentication manager which will handle authentication of users.
Thank you. Authorization in ASP.NET Core is controlled with AuthorizeAttribute and its various parameters. In its most basic form, applying the [Authorize] attribute to a controller, action, or Razor Page, limits access to that component authenticated users.
The next step is to add JWT Helper class that is used to create a Token and Refresh Token and validation of Token. To add class first create “JwtHelpers” folder in the root project then create a class.
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"));
})
According to Your authentication scheme, You should specify attribute this way:
[Authorize(AuthenticationSchemes = "Bearer")]
and this should work as You expect
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()
//...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With