diff options
| author | Jake Mannens <jake@asger.xyz> | 2026-06-19 00:34:17 +1000 |
|---|---|---|
| committer | Jake Mannens <jake@asger.xyz> | 2026-08-21 01:05:38 +1000 |
| commit | b9b0f08222287e8c24ab16b3fc610e04213942f1 (patch) | |
| tree | d97d825c880b6bec25b6488891d69bee0482ff6f /Program.cs | |
| parent | bedb356c07b2a62ce676503f0fcc5a477c2bdbf4 (diff) | |
Added basic infrastructure for JWT authentication
Diffstat (limited to 'Program.cs')
| -rw-r--r-- | Program.cs | 46 |
1 files changed, 46 insertions, 0 deletions
@@ -1,8 +1,11 @@ using HyperBooru.Server.Components; using HyperBooru.Services; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http.Json; using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using System.Security.Cryptography; using System.Text.Json.Serialization; namespace HyperBooru.Server; @@ -39,6 +42,47 @@ public class Program { .GetRequiredService<IConfigService>() .KeyPath)); + // Load our persistently-stored JWT signing key + builder.Services.AddSingleton<RSA>(sp => { + var keyPath = Path.Combine( + sp.GetRequiredService<IConfigService>().KeyPath, + "jwt_key"); + + var protector = sp.GetRequiredService<IDataProtectionProvider>() + .CreateProtector("jwt-signing-key"); + + try { + var unprotected = protector.Unprotect(File.ReadAllBytes(keyPath)); + var rsa = RSA.Create(); + rsa.ImportRSAPrivateKey(unprotected, out var _); + return rsa; + } catch { + var rsa = RSA.Create(4096); + var privKey = rsa.ExportRSAPrivateKey(); + File.WriteAllBytes(keyPath, protector.Protect(privKey)); + return rsa; + } + }); + + // Configure JWT token-based authentication + builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(o => { + var rsa = builder.Services.BuildServiceProvider().GetRequiredService<RSA>(); + o.TokenValidationParameters = new TokenValidationParameters { + ValidateIssuer = false, + ValidateAudience = false, + ValidateIssuerSigningKey = true, + IssuerSigningKey = new RsaSecurityKey(rsa) + }; + }); + + // Configure custom authorization policies + builder.Services.AddAuthorization(o => { + o.AddPolicy(AuthorizationPolicy.NsfwPolicy, p => { + p.RequireClaim("nsfw", "true"); + }); + }); + var app = builder.Build(); // Ensure database is created and it's schema is up to date @@ -52,6 +96,8 @@ public class Program { app.UseExceptionHandler("/Error"); } + app.UseAuthentication(); + app.UseAuthorization(); app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true); app.UseHsts(); app.UseHttpsRedirection(); |
