From a6d6c26b019b36425d89887bbaab79bbded9807c Mon Sep 17 00:00:00 2001 From: Rick van Dam Date: Tue, 21 May 2024 22:12:23 +0200 Subject: [PATCH] add authentication --- .../TestSetup/TestJwtGenerator.cs | 41 +++++++++++++++++++ .../TestSetup/TestWebApi.cs | 17 ++++++-- CleanAspCore/Program.cs | 7 +++- 3 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 CleanAspCore.Api.Tests/TestSetup/TestJwtGenerator.cs diff --git a/CleanAspCore.Api.Tests/TestSetup/TestJwtGenerator.cs b/CleanAspCore.Api.Tests/TestSetup/TestJwtGenerator.cs new file mode 100644 index 0000000..966491b --- /dev/null +++ b/CleanAspCore.Api.Tests/TestSetup/TestJwtGenerator.cs @@ -0,0 +1,41 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Microsoft.IdentityModel.Tokens; + +namespace CleanAspCore.Api.Tests.TestSetup; + +public static class TestJwtGenerator +{ + private const string Audience = "TestUsers"; + private static readonly string _issuer = Guid.NewGuid().ToString(); + private static readonly SecurityKey _securityKey = new SymmetricSecurityKey("A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6A1B2C3D4E5F6"u8.ToArray()) { KeyId = Guid.NewGuid().ToString() }; + private static readonly SigningCredentials _signingCredentials = new SigningCredentials(_securityKey, SecurityAlgorithms.HmacSha256); + + private static readonly JwtSecurityTokenHandler _sTokenHandler = new(); + + public static string GenerateJwtToken(IEnumerable claims) + { + return _sTokenHandler.WriteToken(new JwtSecurityToken(_issuer, Audience, claims, null, DateTime.UtcNow.AddMinutes(20), _signingCredentials)); + } + + public static IServiceCollection ConfigureTestJwt(this IServiceCollection services) + { + services.RemoveAll(typeof(IConfigureOptions)); // Remove any already configured jwt bearer options configurators as we want to be in control of this in the tests. + services.Configure(JwtBearerDefaults.AuthenticationScheme, options => + { + options.Configuration = new OpenIdConnectConfiguration + { + Issuer = _issuer, + SigningKeys = { _securityKey } + }; + options.Audience = Audience; + }); + + return services; + } +} diff --git a/CleanAspCore.Api.Tests/TestSetup/TestWebApi.cs b/CleanAspCore.Api.Tests/TestSetup/TestWebApi.cs index 9ab2534..bc389e0 100644 --- a/CleanAspCore.Api.Tests/TestSetup/TestWebApi.cs +++ b/CleanAspCore.Api.Tests/TestSetup/TestWebApi.cs @@ -1,4 +1,6 @@ -using CleanAspCore.Data; +using System.Net.Http.Headers; +using System.Security.Claims; +using CleanAspCore.Data; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -39,6 +41,7 @@ protected override IHost CreateHost(IHostBuilder builder) services.AddDbContext(c => c .EnableSensitiveDataLogging() .EnableDetailedErrors()); + services.ConfigureTestJwt(); }); builder.ConfigureLogging(loggingBuilder => @@ -75,8 +78,14 @@ public void AssertDatabase(Action seedAction) seedAction(context); } - public T CreateClientFor() => RestService.For(CreateClient(new WebApplicationFactoryClientOptions() + public T CreateClientFor(params Claim[] claims) { - BaseAddress = new Uri("https://localhost") // Prevents https redirection warnings. - })); + var jwt = TestJwtGenerator.GenerateJwtToken(claims); + var client = CreateClient(new WebApplicationFactoryClientOptions + { + BaseAddress = new Uri("https://localhost") // Prevents https redirection warnings. + }); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwt); + return RestService.For(client); + } } diff --git a/CleanAspCore/Program.cs b/CleanAspCore/Program.cs index e0cea25..8eb2515 100644 --- a/CleanAspCore/Program.cs +++ b/CleanAspCore/Program.cs @@ -3,6 +3,7 @@ using CleanAspCore.Data; using MicroElements.Swashbuckle.FluentValidation.AspNetCore; using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; var builder = WebApplication.CreateBuilder(args); @@ -16,7 +17,11 @@ }); builder.Services.AddFluentValidationRulesToSwagger(); -builder.Services.AddAuthorization(); +builder.Services.AddAuthorizationBuilder() + .AddFallbackPolicy("Fallback", new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build()); + builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme);