From 1e6a721dca53cdca33b8b81c1e067f46126e2415 Mon Sep 17 00:00:00 2001 From: Jared Snider Date: Thu, 15 May 2025 22:54:00 -0400 Subject: [PATCH] PM-20532 - WIP on SameSendId Requirement and Handler - need more investigation on if required. --- .../Handlers/SameSendIdHandler.cs | 51 +++++++++++++++++++ .../Requirements/SameSendIdRequirement.cs | 8 +++ .../Utilities/ServiceCollectionExtensions.cs | 1 + 3 files changed, 60 insertions(+) create mode 100644 src/Api/Auth/Authorization/Handlers/SameSendIdHandler.cs create mode 100644 src/Api/Auth/Authorization/Requirements/SameSendIdRequirement.cs diff --git a/src/Api/Auth/Authorization/Handlers/SameSendIdHandler.cs b/src/Api/Auth/Authorization/Handlers/SameSendIdHandler.cs new file mode 100644 index 0000000000..1534482179 --- /dev/null +++ b/src/Api/Auth/Authorization/Handlers/SameSendIdHandler.cs @@ -0,0 +1,51 @@ +using Bit.Api.Auth.Authorization.Requirements; +using Bit.Core.Identity; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace Bit.Api.Auth.Authorization.Handlers; + +public class SameSendIdHandler : AuthorizationHandler +{ + protected override Task HandleRequirementAsync( + AuthorizationHandlerContext context, + SameSendIdRequirement requirement) + { + // TODO: test if this is HTTP context or not + // https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-9.0#access-mvc-request-context-in-handlers + if (context.Resource is AuthorizationFilterContext mvcContext) + { + // TODO: discuss removal of route value completely from endpoints and just use + // SendId claim instead + + // 1) Grab the {id} route value + if (!mvcContext.RouteData.Values.TryGetValue("id", out var rawId)) + { + return Task.CompletedTask; + } + + // TODO: maybe have to handle encodedSendId + + var routeId = rawId?.ToString(); + if (string.IsNullOrEmpty(routeId)) + { + return Task.CompletedTask; + } + + // 2) Grab the send_id claim + var claim = context.User.FindFirst(Claims.SendId); + if (claim == null) + { + return Task.CompletedTask; + } + + // 3) Compare them + if (string.Equals(claim.Value, routeId, StringComparison.OrdinalIgnoreCase)) + { + context.Succeed(requirement); + } + } + + return Task.CompletedTask; + } +} diff --git a/src/Api/Auth/Authorization/Requirements/SameSendIdRequirement.cs b/src/Api/Auth/Authorization/Requirements/SameSendIdRequirement.cs new file mode 100644 index 0000000000..8475f0be48 --- /dev/null +++ b/src/Api/Auth/Authorization/Requirements/SameSendIdRequirement.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Authorization; + +namespace Bit.Api.Auth.Authorization.Requirements; + +// +// Requires that the id of the send request matches the id of the subject claim in the send access token. +// +public class SameSendIdRequirement : IAuthorizationRequirement { } diff --git a/src/Api/Utilities/ServiceCollectionExtensions.cs b/src/Api/Utilities/ServiceCollectionExtensions.cs index 4c8589657e..741297259b 100644 --- a/src/Api/Utilities/ServiceCollectionExtensions.cs +++ b/src/Api/Utilities/ServiceCollectionExtensions.cs @@ -108,5 +108,6 @@ public static class ServiceCollectionExtensions services.AddScoped(); services.AddScoped(); + // services.AddScoped(); } }