From 6bfab118ea3511856f5bc66847e47b0f888c5eca Mon Sep 17 00:00:00 2001 From: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com> Date: Wed, 3 Aug 2022 17:14:28 -0400 Subject: [PATCH 1/2] Replace UrlOverride with BaseUrlOverride --- .../ValidateRequestAttributeTests.cs | 8 ++--- ...ValidationDependencyInjectionExtensions.cs | 2 +- src/Twilio.AspNet.Core/TwilioOptions.cs | 2 +- .../ValidateRequestAttribute.cs | 21 ++++++++++---- src/Twilio.AspNet.Mvc/TwilioConfiguration.cs | 8 ++--- .../ValidateRequestAttribute.cs | 29 ++++++++++++------- src/testapps/AspNetFramework/Web.config | 4 +-- src/testapps/dotnet6/appsettings.json | 2 +- 8 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/Twilio.AspNet.Core.UnitTests/ValidateRequestAttributeTests.cs b/src/Twilio.AspNet.Core.UnitTests/ValidateRequestAttributeTests.cs index b139870..f091771 100644 --- a/src/Twilio.AspNet.Core.UnitTests/ValidateRequestAttributeTests.cs +++ b/src/Twilio.AspNet.Core.UnitTests/ValidateRequestAttributeTests.cs @@ -17,7 +17,7 @@ public class ValidateRequestAttributeTests { AuthToken = "My Twilio:RequestValidation:AuthToken", AllowLocal = false, - UrlOverride = "MY URL OVERRIDE" + BaseUrlOverride = "MY URL OVERRIDE" } }; @@ -30,7 +30,7 @@ public void AddTwilioRequestValidation_With_Callback_Should_Match_Configuration( var requestValidation = ValidTwilioOptions.RequestValidation; options.AuthToken = requestValidation.AuthToken; options.AllowLocal = requestValidation.AllowLocal; - options.UrlOverride = requestValidation.UrlOverride; + options.BaseUrlOverride = requestValidation.BaseUrlOverride; }); var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -71,7 +71,7 @@ public void AddTwilio_Should_Configure_ValidateRequestAttribute() { options.AllowLocal = ValidTwilioOptions.RequestValidation.AllowLocal; options.AuthToken = ValidTwilioOptions.RequestValidation.AuthToken; - options.UrlOverride = ValidTwilioOptions.RequestValidation.UrlOverride; + options.BaseUrlOverride = ValidTwilioOptions.RequestValidation.BaseUrlOverride; }); var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -83,7 +83,7 @@ public void AddTwilio_Should_Configure_ValidateRequestAttribute() Assert.Equal(ValidTwilioOptions.RequestValidation.AllowLocal, attribute.AllowLocal); Assert.Equal(ValidTwilioOptions.RequestValidation.AuthToken, attribute.AuthToken); - Assert.Equal(ValidTwilioOptions.RequestValidation.UrlOverride, attribute.UrlOverride); + Assert.Equal(ValidTwilioOptions.RequestValidation.BaseUrlOverride, attribute.BaseUrlOverride); } [Fact] diff --git a/src/Twilio.AspNet.Core/RequestValidationDependencyInjectionExtensions.cs b/src/Twilio.AspNet.Core/RequestValidationDependencyInjectionExtensions.cs index 48f870c..9f596cd 100644 --- a/src/Twilio.AspNet.Core/RequestValidationDependencyInjectionExtensions.cs +++ b/src/Twilio.AspNet.Core/RequestValidationDependencyInjectionExtensions.cs @@ -41,7 +41,7 @@ private static void SanitizeTwilioRequestValidationOptions(TwilioRequestValidati { // properties can be empty strings, but should be set to null if so if (options.AuthToken == "") options.AuthToken = null; - if (options.UrlOverride == "") options.UrlOverride = null; + if (options.BaseUrlOverride == "") options.BaseUrlOverride = null; } } } \ No newline at end of file diff --git a/src/Twilio.AspNet.Core/TwilioOptions.cs b/src/Twilio.AspNet.Core/TwilioOptions.cs index 489970a..2a2ab43 100644 --- a/src/Twilio.AspNet.Core/TwilioOptions.cs +++ b/src/Twilio.AspNet.Core/TwilioOptions.cs @@ -23,7 +23,7 @@ public class TwilioRequestValidationOptions { public string AuthToken { get; set; } public bool? AllowLocal { get; set; } - public string UrlOverride { get; set; } + public string BaseUrlOverride { get; set; } } public enum CredentialType diff --git a/src/Twilio.AspNet.Core/ValidateRequestAttribute.cs b/src/Twilio.AspNet.Core/ValidateRequestAttribute.cs index adedf7a..528702b 100644 --- a/src/Twilio.AspNet.Core/ValidateRequestAttribute.cs +++ b/src/Twilio.AspNet.Core/ValidateRequestAttribute.cs @@ -27,7 +27,7 @@ public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) return new InternalValidateRequestAttribute( authToken: options.AuthToken, - urlOverride: options.UrlOverride, + baseUrlOverride: options.BaseUrlOverride?.TrimEnd('/'), allowLocal: options.AllowLocal ?? true ); } @@ -35,27 +35,36 @@ public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) internal class InternalValidateRequestAttribute : ActionFilterAttribute { internal string AuthToken { get; set; } - internal string UrlOverride { get; set; } + internal string BaseUrlOverride { get; set; } internal bool AllowLocal { get; set; } /// /// Initializes a new instance of the ValidateRequestAttribute class. /// /// AuthToken for the account used to sign the request - /// The URL to use for validation, if different from Request.Url (sometimes needed if web site is behind a proxy or load-balancer) + /// + /// The Base URL (protocol + hostname) to use for validation, + /// if different from Request.Url (sometimes needed if web site is behind a proxy or load-balancer) + /// /// Skip validation for local requests - public InternalValidateRequestAttribute(string authToken, string urlOverride, bool allowLocal) + public InternalValidateRequestAttribute(string authToken, string baseUrlOverride, bool allowLocal) { AuthToken = authToken; - UrlOverride = urlOverride; + BaseUrlOverride = baseUrlOverride; AllowLocal = allowLocal; } public override void OnActionExecuting(ActionExecutingContext filterContext) { + string urlOverride = null; + if (BaseUrlOverride != null) + { + urlOverride = $"{BaseUrlOverride}{filterContext.HttpContext.Request.Path}"; + } + var validator = new RequestValidationHelper(); - if (!validator.IsValidRequest(filterContext.HttpContext, AuthToken, UrlOverride, AllowLocal)) + if (!validator.IsValidRequest(filterContext.HttpContext, AuthToken, urlOverride, AllowLocal)) { filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden); } diff --git a/src/Twilio.AspNet.Mvc/TwilioConfiguration.cs b/src/Twilio.AspNet.Mvc/TwilioConfiguration.cs index b702c14..8495be5 100644 --- a/src/Twilio.AspNet.Mvc/TwilioConfiguration.cs +++ b/src/Twilio.AspNet.Mvc/TwilioConfiguration.cs @@ -12,11 +12,11 @@ public string AuthToken set => this["authToken"] = value; } - [ConfigurationProperty("urlOverride")] - public string UrlOverride + [ConfigurationProperty("baseUrlOverride")] + public string BaseUrlOverride { - get => (string)this["urlOverride"]; - set => this["urlOverride"] = value; + get => (string)this["baseUrlOverride"]; + set => this["baseUrlOverride"] = value; } [ConfigurationProperty("allowLocal")] diff --git a/src/Twilio.AspNet.Mvc/ValidateRequestAttribute.cs b/src/Twilio.AspNet.Mvc/ValidateRequestAttribute.cs index 83a4f21..a28e71f 100644 --- a/src/Twilio.AspNet.Mvc/ValidateRequestAttribute.cs +++ b/src/Twilio.AspNet.Mvc/ValidateRequestAttribute.cs @@ -8,16 +8,16 @@ namespace Twilio.AspNet.Mvc /// /// Represents an attribute that is used to prevent forgery of a request. /// - public class ValidateRequestAttribute : ActionFilterAttribute + public class ValidateRequestAttribute : ActionFilterAttribute { protected internal string AuthToken { get; set; } - protected internal string UrlOverride { get; set; } + protected internal string BaseUrlOverride { get; set; } protected internal bool AllowLocal { get; set; } /// /// Initializes a new instance of the ValidateRequestAttribute class. /// - public ValidateRequestAttribute() + public ValidateRequestAttribute() { ConfigureProperties(); } @@ -32,29 +32,36 @@ public ValidateRequestAttribute() /// protected virtual void ConfigureProperties() { - var requestValidationConfiguration = ConfigurationManager.GetSection("twilio/requestValidation") as RequestValidationConfigurationSection; + var requestValidationConfiguration = + ConfigurationManager.GetSection("twilio/requestValidation") as RequestValidationConfigurationSection; var appSettings = ConfigurationManager.AppSettings; AuthToken = appSettings["twilio:requestValidation:authToken"] - ?? appSettings["twilio:authToken"] - ?? requestValidationConfiguration?.AuthToken - ?? throw new Exception("Twilio Auth Token not configured"); + ?? appSettings["twilio:authToken"] + ?? requestValidationConfiguration?.AuthToken + ?? throw new Exception("Twilio Auth Token not configured"); - UrlOverride = appSettings["twilio:requestValidation:urlOverride"] - ?? requestValidationConfiguration?.AuthToken; + BaseUrlOverride = appSettings["twilio:requestValidation:baseUrlOverride"] + ?? requestValidationConfiguration?.BaseUrlOverride; var allowLocalAppSetting = appSettings["twilio:requestValidation:allowLocal"]; AllowLocal = allowLocalAppSetting != null ? bool.Parse(allowLocalAppSetting) : requestValidationConfiguration?.AllowLocal - ?? true; + ?? true; } public override void OnActionExecuting(ActionExecutingContext filterContext) { + string urlOverride = null; + if (BaseUrlOverride != null) + { + urlOverride = $"{BaseUrlOverride}{filterContext.HttpContext.Request.Path}"; + } + var validator = new RequestValidationHelper(); - if (!validator.IsValidRequest(filterContext.HttpContext, AuthToken, UrlOverride, AllowLocal)) + if (!validator.IsValidRequest(filterContext.HttpContext, AuthToken, urlOverride, AllowLocal)) { filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden); } diff --git a/src/testapps/AspNetFramework/Web.config b/src/testapps/AspNetFramework/Web.config index 503ac37..99de103 100644 --- a/src/testapps/AspNetFramework/Web.config +++ b/src/testapps/AspNetFramework/Web.config @@ -12,7 +12,7 @@ @@ -22,7 +22,7 @@ - + diff --git a/src/testapps/dotnet6/appsettings.json b/src/testapps/dotnet6/appsettings.json index 2d6012a..9b4e0b4 100644 --- a/src/testapps/dotnet6/appsettings.json +++ b/src/testapps/dotnet6/appsettings.json @@ -21,7 +21,7 @@ "RequestValidation": { "AuthToken": "MyAuthToken!", "AllowLocal": true, - "UrlOverride": "https://??????.ngrok.io/sms" + "BaseUrlOverride": "https://??????.ngrok.io" } } } From 4224048b714b91e83e38840bea13da313393ff1b Mon Sep 17 00:00:00 2001 From: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com> Date: Wed, 3 Aug 2022 18:04:37 -0400 Subject: [PATCH 2/2] Test and fix on .NET Framework --- .../Twilio.AspNet.Mvc.csproj | 2 +- .../ValidateRequestAttribute.cs | 1 + src/testapps/AspNetFramework/Web.config | 124 +++++++++--------- 3 files changed, 64 insertions(+), 63 deletions(-) diff --git a/src/Twilio.AspNet.Mvc/Twilio.AspNet.Mvc.csproj b/src/Twilio.AspNet.Mvc/Twilio.AspNet.Mvc.csproj index 24d901e..6cc5710 100644 --- a/src/Twilio.AspNet.Mvc/Twilio.AspNet.Mvc.csproj +++ b/src/Twilio.AspNet.Mvc/Twilio.AspNet.Mvc.csproj @@ -56,7 +56,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all diff --git a/src/Twilio.AspNet.Mvc/ValidateRequestAttribute.cs b/src/Twilio.AspNet.Mvc/ValidateRequestAttribute.cs index a28e71f..9221523 100644 --- a/src/Twilio.AspNet.Mvc/ValidateRequestAttribute.cs +++ b/src/Twilio.AspNet.Mvc/ValidateRequestAttribute.cs @@ -43,6 +43,7 @@ protected virtual void ConfigureProperties() BaseUrlOverride = appSettings["twilio:requestValidation:baseUrlOverride"] ?? requestValidationConfiguration?.BaseUrlOverride; + if(BaseUrlOverride != null) BaseUrlOverride = BaseUrlOverride.TrimEnd('/'); var allowLocalAppSetting = appSettings["twilio:requestValidation:allowLocal"]; AllowLocal = allowLocalAppSetting != null diff --git a/src/testapps/AspNetFramework/Web.config b/src/testapps/AspNetFramework/Web.config index 99de103..4920513 100644 --- a/src/testapps/AspNetFramework/Web.config +++ b/src/testapps/AspNetFramework/Web.config @@ -4,67 +4,67 @@ https://go.microsoft.com/fwlink/?LinkId=301880 --> - - -
- - - - + +
+ + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file