From cc64675c9cc53a6237d289203968ebcc097e7aae Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Sat, 5 Jul 2025 23:55:40 -0400 Subject: [PATCH] metrics service fixes to auth info --- AobaCore/Extensions.cs | 10 ++----- AobaServer/AobaServer.csproj | 1 + AobaServer/Controllers/AuthController.cs | 4 ++- AobaServer/Models/AuthInfo.cs | 6 ++++- AobaServer/Program.cs | 27 +++++++++++++++---- AobaServer/Proto/Metrics.proto | 12 +++++++++ AobaServer/Services/AuthConfigService.cs | 26 +++++++++++++++++++ AobaServer/Services/MetricsRpcService.cs | 33 ++++++++++++++++++++++++ 8 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 AobaServer/Proto/Metrics.proto create mode 100644 AobaServer/Services/AuthConfigService.cs create mode 100644 AobaServer/Services/MetricsRpcService.cs diff --git a/AobaCore/Extensions.cs b/AobaCore/Extensions.cs index 062acc5..be60109 100644 --- a/AobaCore/Extensions.cs +++ b/AobaCore/Extensions.cs @@ -16,15 +16,9 @@ using System.Threading.Tasks; namespace AobaCore; public static class Extensions { - public static IServiceCollection AddAoba(this IServiceCollection services, string dbString) + public static IServiceCollection AddAoba(this IServiceCollection services) { - var settings = MongoClientSettings.FromConnectionString(dbString); - settings.ClusterConfigurator = cb => cb.Subscribe(new DiagnosticsActivityEventSubscriber()); - var dbClient = new MongoClient(settings); - var db = dbClient.GetDatabase("Aoba"); - - services.AddSingleton(dbClient); - services.AddSingleton(db); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/AobaServer/AobaServer.csproj b/AobaServer/AobaServer.csproj index 6f6047e..c72ec02 100644 --- a/AobaServer/AobaServer.csproj +++ b/AobaServer/AobaServer.csproj @@ -34,6 +34,7 @@ + diff --git a/AobaServer/Controllers/AuthController.cs b/AobaServer/Controllers/AuthController.cs index 72c794c..7a7977f 100644 --- a/AobaServer/Controllers/AuthController.cs +++ b/AobaServer/Controllers/AuthController.cs @@ -1,6 +1,7 @@ using AobaCore.Services; using AobaServer.Models; +using AobaServer.Services; using AobaServer.Utils; using Microsoft.AspNetCore.Authorization; @@ -16,7 +17,7 @@ namespace AobaServer.Controllers; #if DEBUG [AllowAnonymous] [Route("auth")] -public class AuthController(AccountsService accountsService, AuthInfo authInfo) : Controller +public class AuthController(AccountsService accountsService, AuthConfigService authConfig) : Controller { [HttpPost("login")] public async Task Login([FromForm] string username, [FromForm] string password, CancellationToken cancellationToken) @@ -25,6 +26,7 @@ public class AuthController(AccountsService accountsService, AuthInfo authInfo) if (user == null) return Problem("Invalid login Credentials", statusCode: StatusCodes.Status400BadRequest); + var authInfo = await authConfig.GetDefaultAuthInfoAsync(); Response.Cookies.Append("token", user.GetToken(authInfo), new CookieOptions { IsEssential = true, diff --git a/AobaServer/Models/AuthInfo.cs b/AobaServer/Models/AuthInfo.cs index 944c08c..250ee3a 100644 --- a/AobaServer/Models/AuthInfo.cs +++ b/AobaServer/Models/AuthInfo.cs @@ -1,4 +1,6 @@ -using MongoDB.Bson.IO; +using MongoDB.Bson; +using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; using System.Security.Cryptography; using System.Text.Json; @@ -7,6 +9,8 @@ namespace AobaServer.Models; public class AuthInfo { + [BsonId] + public ObjectId Id { get; set; } public required string Issuer { get; set; } public required string Audience { get; set; } public required byte[] SecureKey { get; set; } diff --git a/AobaServer/Program.cs b/AobaServer/Program.cs index dfe1ac8..93f3c9c 100644 --- a/AobaServer/Program.cs +++ b/AobaServer/Program.cs @@ -10,6 +10,9 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Http.Features; using Microsoft.IdentityModel.Tokens; +using MongoDB.Driver; +using MongoDB.Driver.Core.Extensions.DiagnosticSources; + var builder = WebApplication.CreateBuilder(args); builder.WebHost.ConfigureKestrel(o => @@ -33,8 +36,21 @@ builder.Services.AddControllers(opt => opt.ModelBinderProviders.Add(new BsonIdMo builder.Services.AddObersability(builder.Configuration); builder.Services.AddGrpc(); -var authInfo = AuthInfo.LoadOrCreate("Auth.json", "aobaV2", "aoba"); -builder.Services.AddSingleton(authInfo); +//DB +var dbString = config["DB_STRING"]; +var settings = MongoClientSettings.FromConnectionString(dbString); +settings.ClusterConfigurator = cb => cb.Subscribe(new DiagnosticsActivityEventSubscriber()); +var dbClient = new MongoClient(settings); +var db = dbClient.GetDatabase("Aoba"); + +builder.Services.AddSingleton(dbClient); +builder.Services.AddSingleton(db); + +var authCfg = new AuthConfigService(db); +builder.Services.AddSingleton(authCfg); + + +var authInfo = authCfg.GetDefaultAuthInfoAsync().GetAwaiter().GetResult(); var signingKey = new SymmetricSecurityKey(authInfo.SecureKey); var validationParams = new TokenValidationParameters @@ -66,6 +82,7 @@ builder.Services.AddCors(o => }); }); +var metricsAuthInfo = authCfg.GetAuthInfoAsync("aoba", "metrics").GetAwaiter().GetResult(); builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; @@ -73,7 +90,7 @@ builder.Services.AddAuthentication(options => }).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => //Bearer auth { options.TokenValidationParameters = validationParams; - options.TokenHandlers.Add(new MetricsTokenValidator(authInfo)); + options.TokenHandlers.Add(new MetricsTokenValidator(metricsAuthInfo)); options.Events = new JwtBearerEvents { OnMessageReceived = ctx => //Retreive token from cookie if not found in headers @@ -102,8 +119,8 @@ builder.Services.AddAuthentication(options => }; }).AddScheme("Aoba", null); -var dbString = config["DB_STRING"]; -builder.Services.AddAoba(dbString ?? "mongodb://localhost:27017"); + +builder.Services.AddAoba(); builder.Services.Configure(opt => { opt.ValueLengthLimit = int.MaxValue; diff --git a/AobaServer/Proto/Metrics.proto b/AobaServer/Proto/Metrics.proto new file mode 100644 index 0000000..6e227dc --- /dev/null +++ b/AobaServer/Proto/Metrics.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +option csharp_namespace = "Aoba.RPC.Metrics"; +package aoba.Metrics; + +import "Proto/Auth.proto"; +import "google/protobuf/empty.proto"; + + +service Metrics { + rpc GetToken(google.protobuf.Empty) returns (Auth.Jwt); +} \ No newline at end of file diff --git a/AobaServer/Services/AuthConfigService.cs b/AobaServer/Services/AuthConfigService.cs new file mode 100644 index 0000000..9be6696 --- /dev/null +++ b/AobaServer/Services/AuthConfigService.cs @@ -0,0 +1,26 @@ +using AobaServer.Models; + +using MongoDB.Driver; + +namespace AobaServer.Services; + +public class AuthConfigService(IMongoDatabase db) +{ + public IMongoCollection _authInfo = db.GetCollection("auth_config"); + + public async Task GetAuthInfoAsync(string issuer, string audience) + { + var info = await _authInfo.Find("{}").FirstOrDefaultAsync(); + if(info != null) + return info; + + info = AuthInfo.Create(issuer, audience); + await _authInfo.InsertOneAsync(info); + return info; + } + + public Task GetDefaultAuthInfoAsync() + { + return GetAuthInfoAsync("aobaV2", "aoba"); + } +} diff --git a/AobaServer/Services/MetricsRpcService.cs b/AobaServer/Services/MetricsRpcService.cs new file mode 100644 index 0000000..b4d71fb --- /dev/null +++ b/AobaServer/Services/MetricsRpcService.cs @@ -0,0 +1,33 @@ +using Aoba.RPC; +using Aoba.RPC.Auth; + +using Google.Protobuf.WellKnownTypes; + +using Grpc.Core; + +using Microsoft.AspNetCore.Authorization; +using Microsoft.IdentityModel.Tokens; + +using System.IdentityModel.Tokens.Jwt; + +namespace AobaServer.Services; + +public class MetricsRpcService(AuthConfigService authConfig): Aoba.RPC.Metrics.Metrics.MetricsBase +{ + [AllowAnonymous] + public override async Task GetToken(Empty request, ServerCallContext context) + { + var authInfo = await authConfig.GetAuthInfoAsync("aoba", "metrics"); + var handler = new JwtSecurityTokenHandler(); + + var jwt = handler.CreateEncodedJwt(new SecurityTokenDescriptor + { + Audience = authInfo.Audience, + Issuer = authInfo.Issuer, + IssuedAt = DateTime.UtcNow, + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(authInfo.SecureKey), SecurityAlgorithms.HmacSha256) + }); + + return new Jwt { Token = jwt }; + } +}