Files
OpenWarehouse/OpenWarehouse.auth.api/Services/AuthenticationConfigService.cs
T
2025-02-26 23:42:19 +01:00

100 lines
3.7 KiB
C#

using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using OpenWarehouse.auth.api.Common.AuthTokenRepo;
namespace OpenWarehouse.auth.api.Services;
public static class AuthenticationConfigService
{
public static T AddAuthenticationService<T>(this T builder)
where T : IHostApplicationBuilder
{
var privateKeyPath = Path.Combine(builder.Environment.ContentRootPath, "private_key_pkcs8.pem");
var rsa = RSA.Create();
if (!File.Exists(privateKeyPath))
{
rsa = RSA.Create(2048);
var privateKeyPem = ExportPrivateKeyToPem(rsa);
File.WriteAllText(privateKeyPath, privateKeyPem);
Console.WriteLine($"Generated new RSA private key at: {privateKeyPath}");
}
else
{
var privateKey = File.ReadAllText(privateKeyPath);
rsa.ImportFromPem(privateKey);
}
var rsaPublic = rsa.ExportParameters(false);
var rsaSecurityKey = new RsaSecurityKey(rsa)
{
KeyId = "1"
};
// Configure JWT Bearer authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = rsaSecurityKey,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
builder.Configuration["Jwt:AesKey"] ?? throw new InvalidOperationException("Missing Jwt:AesKey in configuration"))),
ValidAudience = builder.Configuration["Jwt:Audience"],
ValidIssuer = builder.Configuration["Jwt:Issuer"],
};
options.Events = new JwtBearerEvents
{
OnTokenValidated = async context =>
{
var tokenBlacklistService = context.HttpContext.RequestServices.GetRequiredService<AuthTokenRepo>();
var token = context.SecurityToken.Id;
if (await tokenBlacklistService.TokenIsLock(guid: token))
{
context.Fail("This token has been revoked.");
}
},
};
});
builder.Services.AddSingleton(new
{
keys = new[]
{
new
{
kty = "RSA",
e = Base64UrlEncoder.Encode(rsaPublic.Exponent),
n = Base64UrlEncoder.Encode(rsaPublic.Modulus),
use = "sig",
alg = "RS256"
}
}
});
return builder;
}
private static string ExportPrivateKeyToPem(RSA rsa)
{
var privateKeyBytes = rsa.ExportPkcs8PrivateKey();
var builder = new StringBuilder();
builder.AppendLine("-----BEGIN PRIVATE KEY-----");
builder.AppendLine(Convert.ToBase64String(privateKeyBytes, Base64FormattingOptions.InsertLineBreaks));
builder.AppendLine("-----END PRIVATE KEY-----");
return builder.ToString();
}
}