From 18b21aa56cd4e969f7bb4834abff7be2979e3c58 Mon Sep 17 00:00:00 2001 From: StefanGreve Date: Mon, 26 Aug 2024 17:11:49 +0200 Subject: [PATCH 1/2] Add starter code for authentication and authorization --- .gitignore | 1 + .../AdvancedSystems.Backend.csproj | 1 + .../ServiceCollectionExtensions.cs | 51 ++++++++++++++++++- .../DependencyInjection/Startup.cs | 5 ++ AdvancedSystems.Backend/Models/CustomClaim.cs | 6 +++ AdvancedSystems.Backend/Models/Roles.cs | 6 +++ AdvancedSystems.Backend/appsettings.json | 5 ++ 7 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 AdvancedSystems.Backend/Models/CustomClaim.cs create mode 100644 AdvancedSystems.Backend/Models/Roles.cs diff --git a/.gitignore b/.gitignore index 785fcf0..c1aab2e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ msbuild.wrn .vscode/ .vs/ .idea/ +appsettings.development.json # Cache *.swp diff --git a/AdvancedSystems.Backend/AdvancedSystems.Backend.csproj b/AdvancedSystems.Backend/AdvancedSystems.Backend.csproj index b64ac70..5b3ce3e 100644 --- a/AdvancedSystems.Backend/AdvancedSystems.Backend.csproj +++ b/AdvancedSystems.Backend/AdvancedSystems.Backend.csproj @@ -13,6 +13,7 @@ + diff --git a/AdvancedSystems.Backend/DependencyInjection/ServiceCollectionExtensions.cs b/AdvancedSystems.Backend/DependencyInjection/ServiceCollectionExtensions.cs index 9195562..12ea72d 100644 --- a/AdvancedSystems.Backend/DependencyInjection/ServiceCollectionExtensions.cs +++ b/AdvancedSystems.Backend/DependencyInjection/ServiceCollectionExtensions.cs @@ -3,6 +3,7 @@ using AdvancedSystems.Backend.Core.Validators; using AdvancedSystems.Backend.Interfaces; +using AdvancedSystems.Backend.Models; using AdvancedSystems.Backend.Models.Settings; using AdvancedSystems.Backend.Services; using AdvancedSystems.Backend.Services.HealthChecks; @@ -12,6 +13,7 @@ using Asp.Versioning; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Http; @@ -21,6 +23,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; using Swashbuckle.AspNetCore.SwaggerGen; @@ -86,9 +89,53 @@ public static IServiceCollection AddCachingService(this IServiceCollection servi } #endregion - + + #region Authentication and Authorization + + public static IServiceCollection AddJwtAuth(this IServiceCollection services) + { + var authBuilder = services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; + }); + + authBuilder.AddJwtBearer(options => + { + options.TokenValidationParameters = new TokenValidationParameters + { + // TODO: configure token validation parameters properly + IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("secret")), + ValidateIssuerSigningKey = true, + ValidateLifetime = true, + ValidIssuer = "issuer", + ValidAudience = "audience", + ValidateIssuer = true, + ValidateAudience = true, + }; + }); + + services.AddJwtPolicy(); + + return services; + } + + public static IServiceCollection AddJwtPolicy(this IServiceCollection services) + { + return services.AddAuthorization(options => + { + options.AddPolicy(Roles.Admin, policy => + { + policy.RequireClaim(CustomClaim.IsAdmin, "true"); + }); + }); + } + + #endregion + #region Health Checks - + public static IServiceCollection AddBackendHealthChecks(this IServiceCollection services) { services.AddSingleton(); diff --git a/AdvancedSystems.Backend/DependencyInjection/Startup.cs b/AdvancedSystems.Backend/DependencyInjection/Startup.cs index 7e844bf..f0f12cf 100644 --- a/AdvancedSystems.Backend/DependencyInjection/Startup.cs +++ b/AdvancedSystems.Backend/DependencyInjection/Startup.cs @@ -54,6 +54,8 @@ public static IServiceCollection ConfigureServices(this IServiceCollection servi options.LowercaseUrls = true; }); + services.AddJwtAuth(); + services.AddControllers(); services.AddBackendHealthChecks(); @@ -85,6 +87,9 @@ public static void Configure(this WebApplication app, IHostEnvironment environme app.UseHsts(); } + app.UseAuthentication(); + app.UseAuthorization(); + app.UseHttpsRedirection(); app.UseStatusCodePages(); app.UseExceptionHandler(); diff --git a/AdvancedSystems.Backend/Models/CustomClaim.cs b/AdvancedSystems.Backend/Models/CustomClaim.cs new file mode 100644 index 0000000..e59ca1c --- /dev/null +++ b/AdvancedSystems.Backend/Models/CustomClaim.cs @@ -0,0 +1,6 @@ +namespace AdvancedSystems.Backend.Models; + +public static class CustomClaim +{ + public static readonly string IsAdmin = "is_admin"; +} diff --git a/AdvancedSystems.Backend/Models/Roles.cs b/AdvancedSystems.Backend/Models/Roles.cs new file mode 100644 index 0000000..00b0760 --- /dev/null +++ b/AdvancedSystems.Backend/Models/Roles.cs @@ -0,0 +1,6 @@ +namespace AdvancedSystems.Backend.Models; + +public static class Roles +{ + public static readonly string Admin = "Admin"; +} diff --git a/AdvancedSystems.Backend/appsettings.json b/AdvancedSystems.Backend/appsettings.json index 886f7f2..a398b8f 100644 --- a/AdvancedSystems.Backend/appsettings.json +++ b/AdvancedSystems.Backend/appsettings.json @@ -2,6 +2,11 @@ "AppSettings": { "DefaultApiVersion": 1.0 }, + "Jwt": { + "Key": "", + "Issuer": "", + "Audience": "" + }, "NLog": { "extensions": [ { From b5651c6f661c6824913d02fd0f3b36a3d1606c96 Mon Sep 17 00:00:00 2001 From: StefanGreve Date: Mon, 26 Aug 2024 21:32:53 +0200 Subject: [PATCH 2/2] Code style --- .../DependencyInjection/ServiceCollectionExtensions.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/AdvancedSystems.Backend/DependencyInjection/ServiceCollectionExtensions.cs b/AdvancedSystems.Backend/DependencyInjection/ServiceCollectionExtensions.cs index 12ea72d..da26990 100644 --- a/AdvancedSystems.Backend/DependencyInjection/ServiceCollectionExtensions.cs +++ b/AdvancedSystems.Backend/DependencyInjection/ServiceCollectionExtensions.cs @@ -127,7 +127,7 @@ public static IServiceCollection AddJwtPolicy(this IServiceCollection services) { options.AddPolicy(Roles.Admin, policy => { - policy.RequireClaim(CustomClaim.IsAdmin, "true"); + policy.RequireClaim(CustomClaim.IsAdmin, "true").RequireAuthenticatedUser(); }); }); } @@ -173,12 +173,16 @@ public static IServiceCollection AddBackendDocumentation(this IServiceCollection { var settings = configuration.GetRequiredSection(nameof(AppSettings)).Get(); - services.AddApiVersioning(option => { + var apiVersionBuilder = services.AddApiVersioning(option => { option.DefaultApiVersion = new ApiVersion(settings!.DefaultApiVersion); option.AssumeDefaultVersionWhenUnspecified = true; option.ReportApiVersions = true; option.ApiVersionReader = new MediaTypeApiVersionReader("api-version"); - }).AddMvc().AddApiExplorer(); + }); + + apiVersionBuilder + .AddMvc() + .AddApiExplorer(); services.TryAdd(ServiceDescriptor.Transient, ConfigureSwaggerOptions>()); services.AddSwaggerGen(option => option.OperationFilter());