From 0ec37b1c4af2ac48ba78ac95e92f6e7f5df8f2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 15 Sep 2022 10:03:58 +0300 Subject: [PATCH] Validate Dapr App API Tokens. --- .../AbpAspNetCoreMvcDaprPubSubController.cs | 2 + .../Mvc/Dapr/DaprAppApiTokenValidator.cs | 62 +++++++++++++++++++ .../Mvc/Dapr/DaprHttpContextExtensions.cs | 31 ++++++++++ .../Mvc/Dapr/IDaprAppApiTokenValidator.cs | 10 +++ 4 files changed, 105 insertions(+) create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/DaprAppApiTokenValidator.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/DaprHttpContextExtensions.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/IDaprAppApiTokenValidator.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprPubSubController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprPubSubController.cs index c97e793b53..674e227cd0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprPubSubController.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus/Volo/Abp/AspNetCore/Mvc/Dapr/EventBus/Controllers/AbpAspNetCoreMvcDaprPubSubController.cs @@ -21,6 +21,8 @@ public class AbpAspNetCoreMvcDaprPubSubController : AbpController [HttpPost(AbpAspNetCoreMvcDaprPubSubConsts.DaprEventCallbackUrl)] public virtual async Task EventsAsync() { + this.HttpContext.ValidateDaprAppApiToken(); + var bodyJsonDocument = await JsonDocument.ParseAsync(HttpContext.Request.Body); var request = JsonSerializer.Deserialize(bodyJsonDocument.RootElement.GetRawText(), HttpContext.RequestServices.GetRequiredService>().Value.JsonSerializerOptions); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/DaprAppApiTokenValidator.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/DaprAppApiTokenValidator.cs new file mode 100644 index 0000000000..aebfabeecd --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/DaprAppApiTokenValidator.cs @@ -0,0 +1,62 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Authorization; +using Volo.Abp.Dapr; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.Dapr; + +public class DaprAppApiTokenValidator : IDaprAppApiTokenValidator, ISingletonDependency +{ + public virtual void CheckDaprAppApiToken(HttpContext httpContext) + { + var expectedAppApiToken = GetConfiguredAppApiToken(httpContext); + if (expectedAppApiToken.IsNullOrWhiteSpace()) + { + return; + } + + var headerAppApiToken = GetDaprAppApiTokenOrNull(httpContext); + if (headerAppApiToken.IsNullOrWhiteSpace()) + { + throw new AbpAuthorizationException("Expected Dapr App API Token is not provided! Dapr should set the 'dapr-api-token' HTTP header."); + } + + if (expectedAppApiToken != headerAppApiToken) + { + throw new AbpAuthorizationException("The Dapr App API Token (provided in the 'dapr-api-token' HTTP header) doesn't match the expected value!"); + } + } + + public virtual bool IsValidDaprAppApiToken(HttpContext httpContext) + { + var expectedAppApiToken = GetConfiguredAppApiToken(httpContext); + if (expectedAppApiToken.IsNullOrWhiteSpace()) + { + return true; + } + + var headerAppApiToken = GetDaprAppApiTokenOrNull(httpContext); + return expectedAppApiToken == headerAppApiToken; + } + + public virtual string? GetDaprAppApiTokenOrNull(HttpContext httpContext) + { + string apiTokenHeader = httpContext.Request.Headers["dapr-api-token"]; + if (string.IsNullOrEmpty(apiTokenHeader) || apiTokenHeader.Length < 1) + { + return null; + } + + return apiTokenHeader; + } + + protected virtual string GetConfiguredAppApiToken(HttpContext httpContext) + { + var expectedAppApiToken = httpContext + .RequestServices + .GetRequiredService() + .GetAppApiToken(); + return expectedAppApiToken; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/DaprHttpContextExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/DaprHttpContextExtensions.cs new file mode 100644 index 0000000000..a35fbef2dc --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/DaprHttpContextExtensions.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.Dapr; + +public static class DaprHttpContextExtensions +{ + public static void ValidateDaprAppApiToken(this HttpContext httpContext) + { + httpContext + .RequestServices + .GetRequiredService() + .CheckDaprAppApiToken(httpContext); + } + + public static bool IsValidDaprAppApiToken(this HttpContext httpContext) + { + return httpContext + .RequestServices + .GetRequiredService() + .IsValidDaprAppApiToken(httpContext); + } + + public static string? GetDaprAppApiTokenOrNull(HttpContext httpContext) + { + return httpContext + .RequestServices + .GetRequiredService() + .GetDaprAppApiTokenOrNull(httpContext); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/IDaprAppApiTokenValidator.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/IDaprAppApiTokenValidator.cs new file mode 100644 index 0000000000..b3de839fc5 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Dapr/Volo/Abp/AspNetCore/Mvc/Dapr/IDaprAppApiTokenValidator.cs @@ -0,0 +1,10 @@ +using Microsoft.AspNetCore.Http; + +namespace Volo.Abp.AspNetCore.Mvc.Dapr; + +public interface IDaprAppApiTokenValidator +{ + void CheckDaprAppApiToken(HttpContext httpContext); + bool IsValidDaprAppApiToken(HttpContext httpContext); + string? GetDaprAppApiTokenOrNull(HttpContext httpContext); +} \ No newline at end of file