using System.Text.Json; using System.Text.Json.Serialization; using Azaion.Missions.JwksMock.Services; namespace Azaion.Missions.JwksMock.Endpoints; public static class SignEndpoint { /// /// POST /sign. Body is a small JSON object documented in /// _docs/02_document/tests/test-data.md ยง JWKS mock token-minting contract. /// All fields optional; omitted fields fall back to mock defaults. /// public static async Task Handle(HttpContext ctx, TokenSigner signer) { SignBody? body; try { body = await JsonSerializer.DeserializeAsync( ctx.Request.Body, SignBodyContext.Default.SignBody, ctx.RequestAborted); } catch (JsonException ex) { return Results.BadRequest(new { error = "invalid_json", detail = ex.Message }); } body ??= new SignBody(); try { var result = signer.Sign(new SignRequest( Issuer: body.Iss, Audience: body.Aud, ExpOffsetSeconds: body.ExpOffsetSeconds, Permissions: body.Permissions, Subject: body.Sub, AlgOverride: body.AlgOverride, KidOverride: body.KidOverride)); return Results.Json(new SignResponse(result.Token, result.Kid), SignBodyContext.Default.SignResponse); } catch (ArgumentException ex) { return Results.BadRequest(new { error = "invalid_arg", detail = ex.Message }); } } } public sealed record SignBody( [property: JsonPropertyName("iss")] string? Iss = null, [property: JsonPropertyName("aud")] string? Aud = null, [property: JsonPropertyName("sub")] string? Sub = null, [property: JsonPropertyName("exp_offset_seconds")] int? ExpOffsetSeconds = null, [property: JsonPropertyName("permissions")] string? Permissions = null, [property: JsonPropertyName("alg_override")] string? AlgOverride = null, [property: JsonPropertyName("kid_override")] string? KidOverride = null); public sealed record SignResponse( [property: JsonPropertyName("token")] string Token, [property: JsonPropertyName("kid")] string Kid); [JsonSerializable(typeof(SignBody))] [JsonSerializable(typeof(SignResponse))] [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower)] internal sealed partial class SignBodyContext : JsonSerializerContext;