From a64dbe12a110e3ea5196a584c8a0bd81af1731ce Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 10 Jun 2024 13:31:51 +0200 Subject: [PATCH] OpenIddict should only handle /umbraco/ requests (#16549) --- .../ProcessRequestContextHandler.cs | 53 +++++++++++++++++++ .../UmbracoBuilderAuthExtensions.cs | 16 ++++++ 2 files changed, 69 insertions(+) create mode 100644 src/Umbraco.Cms.Api.Common/DependencyInjection/ProcessRequestContextHandler.cs diff --git a/src/Umbraco.Cms.Api.Common/DependencyInjection/ProcessRequestContextHandler.cs b/src/Umbraco.Cms.Api.Common/DependencyInjection/ProcessRequestContextHandler.cs new file mode 100644 index 000000000000..c680ab6b3409 --- /dev/null +++ b/src/Umbraco.Cms.Api.Common/DependencyInjection/ProcessRequestContextHandler.cs @@ -0,0 +1,53 @@ +using Microsoft.AspNetCore.Http; +using OpenIddict.Server; +using OpenIddict.Validation; +using Umbraco.Cms.Core; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Api.Common.DependencyInjection; + +public class ProcessRequestContextHandler + : IOpenIddictServerHandler, IOpenIddictValidationHandler +{ + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly string _backOfficePathSegment; + + public ProcessRequestContextHandler(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + _backOfficePathSegment = Constants.System.DefaultUmbracoPath.TrimStart(Constants.CharArrays.Tilde) + .EnsureStartsWith('/') + .EnsureEndsWith('/'); + } + + public ValueTask HandleAsync(OpenIddictServerEvents.ProcessRequestContext context) + { + if (SkipOpenIddictHandlingForRequest()) + { + context.SkipRequest(); + } + + return ValueTask.CompletedTask; + } + + public ValueTask HandleAsync(OpenIddictValidationEvents.ProcessRequestContext context) + { + if (SkipOpenIddictHandlingForRequest()) + { + context.SkipRequest(); + } + + return ValueTask.CompletedTask; + } + + private bool SkipOpenIddictHandlingForRequest() + { + var requestPath = _httpContextAccessor.HttpContext?.Request.Path.Value; + if (requestPath.IsNullOrWhiteSpace()) + { + return false; + } + + return requestPath.StartsWith(_backOfficePathSegment) is false; + } +} diff --git a/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs b/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs index b61f842b5a80..7e730695f3a6 100644 --- a/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs +++ b/src/Umbraco.Cms.Api.Common/DependencyInjection/UmbracoBuilderAuthExtensions.cs @@ -2,6 +2,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; +using OpenIddict.Server; +using OpenIddict.Validation; using Umbraco.Cms.Api.Common.Security; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; @@ -96,6 +98,13 @@ private static void ConfigureOpenIddict(IUmbracoBuilder builder) options .AddEncryptionKey(new SymmetricSecurityKey(RandomNumberGenerator.GetBytes(32))) // generate a cryptographically secure random 256-bits key .AddSigningKey(new RsaSecurityKey(RSA.Create(keySizeInBits: 2048))); // generate RSA key with recommended size of 2048-bits + + // Add custom handler for the "ProcessRequestContext" server event, to stop OpenIddict from handling + // every last request to the server (including front-end requests). + options.AddEventHandler(configuration => + { + configuration.UseSingletonHandler().SetOrder(OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers.ResolveRequestUri.Descriptor.Order - 1); + }); }) // Register the OpenIddict validation components. @@ -113,6 +122,13 @@ private static void ConfigureOpenIddict(IUmbracoBuilder builder) // Use ASP.NET Core Data Protection for tokens instead of JWT. (see note in AddServer) options.UseDataProtection(); + + // Add custom handler for the "ProcessRequestContext" validation event, to stop OpenIddict from handling + // every last request to the server (including front-end requests). + options.AddEventHandler(configuration => + { + configuration.UseSingletonHandler().SetOrder(OpenIddict.Validation.AspNetCore.OpenIddictValidationAspNetCoreHandlers.ResolveRequestUri.Descriptor.Order - 1); + }); }); builder.Services.AddRecurringBackgroundJob();