From af1fb2e8907b3dce6d50558a6b90874a6680837b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Fri, 22 Nov 2019 21:42:56 +0100 Subject: [PATCH] Split request caching into 2 separate options --- .../OpenIddictServerAspNetCoreBuilder.cs | 45 ++++++++++---- .../OpenIddictServerAspNetCoreExtensions.cs | 3 +- ...penIddictServerAspNetCoreHandlerFilters.cs | 48 +++++++++++---- ...ServerAspNetCoreHandlers.Authentication.cs | 8 +-- ...nIddictServerAspNetCoreHandlers.Session.cs | 8 +-- .../OpenIddictServerAspNetCoreOptions.cs | 28 ++++++--- .../OpenIddictServerOwinBuilder.cs | 41 ++++++++++--- .../OpenIddictServerOwinExtensions.cs | 3 +- .../OpenIddictServerOwinHandlerFilters.cs | 61 +++++++++++++------ ...IddictServerOwinHandlers.Authentication.cs | 8 +-- .../OpenIddictServerOwinHandlers.Session.cs | 8 +-- .../OpenIddictServerOwinOptions.cs | 26 ++++++-- 12 files changed, 203 insertions(+), 84 deletions(-) diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs index 84fb21e8..c15bbcec 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreBuilder.cs @@ -120,39 +120,62 @@ namespace Microsoft.Extensions.DependencyInjection => Configure(options => options.EnableVerificationEndpointPassthrough = true); /// - /// Enables request caching, so that both authorization and logout requests + /// Enables authorization endpoint caching, so that authorization requests /// are automatically stored in the distributed cache, which allows flowing /// large payloads across requests. Enabling this option is recommended /// when using external authentication providers or when large GET or POST /// OpenID Connect authorization requests support is required. /// /// The . - public OpenIddictServerAspNetCoreBuilder EnableRequestCaching() - => Configure(options => options.EnableRequestCaching = true); + public OpenIddictServerAspNetCoreBuilder EnableAuthorizationEndpointCaching() + => Configure(options => options.EnableAuthorizationEndpointCaching = true); /// - /// Enables status code pages integration support. Once enabled, errors generated - /// by the interactive authorization and logout endpoints can be handled by ASP.NET Core. + /// Enables logout endpoint caching, so that logout requests + /// are automatically stored in the distributed cache. + /// + /// The . + public OpenIddictServerAspNetCoreBuilder EnableLogoutEndpointCaching() + => Configure(options => options.EnableLogoutEndpointCaching = true); + + /// + /// Enables status code pages integration support. Once enabled, errors + /// generated by the interactive endpoints can be handled by ASP.NET Core. /// /// The . public OpenIddictServerAspNetCoreBuilder EnableStatusCodePagesIntegration() => Configure(options => options.EnableStatusCodePagesIntegration = true); /// - /// Sets the caching policy used to determine how long the authorization and - /// end session requests should be cached by the distributed cache implementation. - /// Note: the specified policy is only used when request caching is explicitly enabled. + /// Sets the caching policy used by the authorization endpoint. + /// Note: the specified policy is only used when caching is explicitly enabled. + /// + /// The caching policy. + /// The . + public OpenIddictServerAspNetCoreBuilder SetAuthorizationEndpointCachingPolicy([NotNull] DistributedCacheEntryOptions policy) + { + if (policy == null) + { + throw new ArgumentNullException(nameof(policy)); + } + + return Configure(options => options.AuthorizationEndpointCachingPolicy = policy); + } + + /// + /// Sets the caching policy used by the logout endpoint. + /// Note: the specified policy is only used when caching is explicitly enabled. /// - /// The request caching policy. + /// The caching policy. /// The . - public OpenIddictServerAspNetCoreBuilder SetRequestCachingPolicy([NotNull] DistributedCacheEntryOptions policy) + public OpenIddictServerAspNetCoreBuilder SetLogoutEndpointCachingPolicy([NotNull] DistributedCacheEntryOptions policy) { if (policy == null) { throw new ArgumentNullException(nameof(policy)); } - return Configure(options => options.RequestCachingPolicy = policy); + return Configure(options => options.LogoutEndpointCachingPolicy = policy); } /// diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreExtensions.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreExtensions.cs index 03383cb8..9dac76c2 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreExtensions.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreExtensions.cs @@ -44,12 +44,13 @@ namespace Microsoft.Extensions.DependencyInjection builder.Services.TryAdd(DefaultHandlers.Select(descriptor => descriptor.ServiceDescriptor)); // Register the built-in filters used by the default OpenIddict ASP.NET Core server event handlers. + builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); + builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); - builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlerFilters.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlerFilters.cs index 51238a3b..c052ee50 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlerFilters.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlerFilters.cs @@ -20,6 +20,27 @@ namespace OpenIddict.Server.AspNetCore [EditorBrowsable(EditorBrowsableState.Advanced)] public static class OpenIddictServerAspNetCoreHandlerFilters { + /// + /// Represents a filter that excludes the associated handlers if authorization endpoint caching was not enabled. + /// + public class RequireAuthorizationEndpointCachingEnabled : IOpenIddictServerHandlerFilter + { + private readonly IOptionsMonitor _options; + + public RequireAuthorizationEndpointCachingEnabled([NotNull] IOptionsMonitor options) + => _options = options; + + public ValueTask IsActiveAsync([NotNull] BaseContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + return new ValueTask(_options.CurrentValue.EnableAuthorizationEndpointCaching); + } + } + /// /// Represents a filter that excludes the associated handlers if the /// pass-through mode was not enabled for the authorization endpoint. @@ -78,15 +99,15 @@ namespace OpenIddict.Server.AspNetCore return new ValueTask(context.Transaction.GetHttpRequest() != null); } } + /// - /// Represents a filter that excludes the associated handlers if the - /// pass-through mode was not enabled for the logout endpoint. + /// Represents a filter that excludes the associated handlers if logout endpoint caching was not enabled. /// - public class RequireLogoutEndpointPassthroughEnabled : IOpenIddictServerHandlerFilter + public class RequireLogoutEndpointCachingEnabled : IOpenIddictServerHandlerFilter { private readonly IOptionsMonitor _options; - public RequireLogoutEndpointPassthroughEnabled([NotNull] IOptionsMonitor options) + public RequireLogoutEndpointCachingEnabled([NotNull] IOptionsMonitor options) => _options = options; public ValueTask IsActiveAsync([NotNull] BaseContext context) @@ -96,18 +117,19 @@ namespace OpenIddict.Server.AspNetCore throw new ArgumentNullException(nameof(context)); } - return new ValueTask(_options.CurrentValue.EnableLogoutEndpointPassthrough); + return new ValueTask(_options.CurrentValue.EnableLogoutEndpointCaching); } } /// - /// Represents a filter that excludes the associated handlers if the HTTPS requirement was disabled. + /// Represents a filter that excludes the associated handlers if the + /// pass-through mode was not enabled for the logout endpoint. /// - public class RequireTransportSecurityRequirementEnabled : IOpenIddictServerHandlerFilter + public class RequireLogoutEndpointPassthroughEnabled : IOpenIddictServerHandlerFilter { private readonly IOptionsMonitor _options; - public RequireTransportSecurityRequirementEnabled([NotNull] IOptionsMonitor options) + public RequireLogoutEndpointPassthroughEnabled([NotNull] IOptionsMonitor options) => _options = options; public ValueTask IsActiveAsync([NotNull] BaseContext context) @@ -117,18 +139,18 @@ namespace OpenIddict.Server.AspNetCore throw new ArgumentNullException(nameof(context)); } - return new ValueTask(!_options.CurrentValue.DisableTransportSecurityRequirement); + return new ValueTask(_options.CurrentValue.EnableLogoutEndpointPassthrough); } } /// - /// Represents a filter that excludes the associated handlers if request caching was not enabled. + /// Represents a filter that excludes the associated handlers if the HTTPS requirement was disabled. /// - public class RequireRequestCachingEnabled : IOpenIddictServerHandlerFilter + public class RequireTransportSecurityRequirementEnabled : IOpenIddictServerHandlerFilter { private readonly IOptionsMonitor _options; - public RequireRequestCachingEnabled([NotNull] IOptionsMonitor options) + public RequireTransportSecurityRequirementEnabled([NotNull] IOptionsMonitor options) => _options = options; public ValueTask IsActiveAsync([NotNull] BaseContext context) @@ -138,7 +160,7 @@ namespace OpenIddict.Server.AspNetCore throw new ArgumentNullException(nameof(context)); } - return new ValueTask(_options.CurrentValue.EnableRequestCaching); + return new ValueTask(!_options.CurrentValue.DisableTransportSecurityRequirement); } } diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs index 4ff9db39..4e71c24b 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Authentication.cs @@ -81,7 +81,7 @@ namespace OpenIddict.Server.AspNetCore public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(ExtractGetOrPostRequest.Descriptor.Order + 1_000) .Build(); @@ -168,7 +168,7 @@ namespace OpenIddict.Server.AspNetCore public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(RestoreCachedRequestParameters.Descriptor.Order + 1_000) .Build(); @@ -228,7 +228,7 @@ namespace OpenIddict.Server.AspNetCore // Note: the cache key is always prefixed with a specific marker // to avoid collisions with the other types of cached payloads. await _cache.SetAsync(Cache.AuthorizationRequest + context.Request.RequestId, - stream.ToArray(), _options.CurrentValue.RequestCachingPolicy); + stream.ToArray(), _options.CurrentValue.AuthorizationEndpointCachingPolicy); // Create a new GET authorization request containing only the request_id parameter. var address = QueryHelpers.AddQueryString( @@ -267,7 +267,7 @@ namespace OpenIddict.Server.AspNetCore public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(ProcessFormPostResponse.Descriptor.Order - 1_000) .Build(); diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs index 9d6bb16f..a139eaa7 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.Session.cs @@ -80,7 +80,7 @@ namespace OpenIddict.Server.AspNetCore public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(ExtractGetOrPostRequest.Descriptor.Order + 1_000) .Build(); @@ -167,7 +167,7 @@ namespace OpenIddict.Server.AspNetCore public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(RestoreCachedRequestParameters.Descriptor.Order + 1_000) .Build(); @@ -227,7 +227,7 @@ namespace OpenIddict.Server.AspNetCore // Note: the cache key is always prefixed with a specific marker // to avoid collisions with the other types of cached payloads. await _cache.SetAsync(Cache.LogoutRequest + context.Request.RequestId, - stream.ToArray(), _options.CurrentValue.RequestCachingPolicy); + stream.ToArray(), _options.CurrentValue.LogoutEndpointCachingPolicy); // Create a new GET logout request containing only the request_id parameter. var address = QueryHelpers.AddQueryString( @@ -266,7 +266,7 @@ namespace OpenIddict.Server.AspNetCore public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(ProcessQueryResponse.Descriptor.Order - 1_000) .Build(); diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreOptions.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreOptions.cs index 25fba02d..fd311c26 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreOptions.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreOptions.cs @@ -72,26 +72,40 @@ namespace OpenIddict.Server.AspNetCore public bool EnableVerificationEndpointPassthrough { get; set; } /// - /// Gets or sets a boolean indicating whether request caching should be enabled. - /// When enabled, both authorization and logout requests are automatically stored + /// Gets or sets a boolean indicating whether requests received by the authorization endpoint + /// should be cached. When enabled, authorization requests are automatically stored /// in the distributed cache, which allows flowing large payloads across requests. /// Enabling this option is recommended when using external authentication providers /// or when large GET or POST OpenID Connect authorization requests support is required. /// - public bool EnableRequestCaching { get; set; } + public bool EnableAuthorizationEndpointCaching { get; set; } + + /// + /// Gets or sets a boolean indicating whether requests received by the logout endpoint should be cached. + /// When enabled, authorization requests are automatically stored in the distributed cache. + /// + public bool EnableLogoutEndpointCaching { get; set; } /// /// Gets or sets a boolean indicating whether integration with the status code pages /// middleware should be enabled or not. Once enabled, errors generated by the OpenIddict - /// interactive authorization and logout endpoints can be handled by ASP.NET Core. + /// interactive endpoints (e.g authorization or logout) can be handled by ASP.NET Core. /// public bool EnableStatusCodePagesIntegration { get; set; } /// - /// Gets or sets the caching policy used to determine how long the authorization - /// and end session requests should be cached by the distributed cache implementation. + /// Gets or sets the caching policy used by the authorization endpoint. + /// + public DistributedCacheEntryOptions AuthorizationEndpointCachingPolicy { get; set; } = new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1), + SlidingExpiration = TimeSpan.FromMinutes(30) + }; + + /// + /// Gets or sets the caching policy used by the logout endpoint. /// - public DistributedCacheEntryOptions RequestCachingPolicy { get; set; } = new DistributedCacheEntryOptions + public DistributedCacheEntryOptions LogoutEndpointCachingPolicy { get; set; } = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1), SlidingExpiration = TimeSpan.FromMinutes(30) diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs index d5950bb3..18790059 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinBuilder.cs @@ -120,31 +120,54 @@ namespace Microsoft.Extensions.DependencyInjection => Configure(options => options.EnableVerificationEndpointPassthrough = true); /// - /// Enables request caching, so that both authorization and logout requests + /// Enables authorization endpoint caching, so that authorization requests /// are automatically stored in the distributed cache, which allows flowing /// large payloads across requests. Enabling this option is recommended /// when using external authentication providers or when large GET or POST /// OpenID Connect authorization requests support is required. /// /// The . - public OpenIddictServerOwinBuilder EnableRequestCaching() - => Configure(options => options.EnableRequestCaching = true); + public OpenIddictServerOwinBuilder EnableAuthorizationEndpointCaching() + => Configure(options => options.EnableAuthorizationEndpointCaching = true); /// - /// Sets the caching policy used to determine how long the authorization and - /// end session requests should be cached by the distributed cache implementation. - /// Note: the specified policy is only used when request caching is explicitly enabled. + /// Enables logout endpoint caching, so that logout requests + /// are automatically stored in the distributed cache. /// - /// The request caching policy. /// The . - public OpenIddictServerOwinBuilder SetRequestCachingPolicy([NotNull] DistributedCacheEntryOptions policy) + public OpenIddictServerOwinBuilder EnableLogoutEndpointCaching() + => Configure(options => options.EnableLogoutEndpointCaching = true); + + /// + /// Sets the caching policy used by the authorization endpoint. + /// Note: the specified policy is only used when caching is explicitly enabled. + /// + /// The caching policy. + /// The . + public OpenIddictServerOwinBuilder SetAuthorizationEndpointCachingPolicy([NotNull] DistributedCacheEntryOptions policy) + { + if (policy == null) + { + throw new ArgumentNullException(nameof(policy)); + } + + return Configure(options => options.AuthorizationEndpointCachingPolicy = policy); + } + + /// + /// Sets the caching policy used by the logout endpoint. + /// Note: the specified policy is only used when caching is explicitly enabled. + /// + /// The caching policy. + /// The . + public OpenIddictServerOwinBuilder SetLogoutEndpointCachingPolicy([NotNull] DistributedCacheEntryOptions policy) { if (policy == null) { throw new ArgumentNullException(nameof(policy)); } - return Configure(options => options.RequestCachingPolicy = policy); + return Configure(options => options.LogoutEndpointCachingPolicy = policy); } /// diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinExtensions.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinExtensions.cs index ef7e66b8..6bc1d746 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinExtensions.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinExtensions.cs @@ -46,12 +46,13 @@ namespace Microsoft.Extensions.DependencyInjection builder.Services.TryAdd(DefaultHandlers.Select(descriptor => descriptor.ServiceDescriptor)); // Register the built-in filters used by the default OpenIddict OWIN server event handlers. + builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); + builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); - builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlerFilters.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlerFilters.cs index 7883d9b0..7419833a 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlerFilters.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlerFilters.cs @@ -18,6 +18,27 @@ namespace OpenIddict.Server.Owin /// public static class OpenIddictServerOwinHandlerFilters { + /// + /// Represents a filter that excludes the associated handlers if authorization endpoint caching was not enabled. + /// + public class RequireAuthorizationEndpointCachingEnabled : IOpenIddictServerHandlerFilter + { + private readonly IOptionsMonitor _options; + + public RequireAuthorizationEndpointCachingEnabled([NotNull] IOptionsMonitor options) + => _options = options; + + public ValueTask IsActiveAsync([NotNull] BaseContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + return new ValueTask(_options.CurrentValue.EnableAuthorizationEndpointCaching); + } + } + /// /// Represents a filter that excludes the associated handlers if the /// pass-through mode was not enabled for the authorization endpoint. @@ -62,14 +83,13 @@ namespace OpenIddict.Server.Owin } /// - /// Represents a filter that excludes the associated handlers if the - /// pass-through mode was not enabled for the logout endpoint. + /// Represents a filter that excludes the associated handlers if logout endpoint caching was not enabled. /// - public class RequireLogoutEndpointPassthroughEnabled : IOpenIddictServerHandlerFilter + public class RequireLogoutEndpointCachingEnabled : IOpenIddictServerHandlerFilter { private readonly IOptionsMonitor _options; - public RequireLogoutEndpointPassthroughEnabled([NotNull] IOptionsMonitor options) + public RequireLogoutEndpointCachingEnabled([NotNull] IOptionsMonitor options) => _options = options; public ValueTask IsActiveAsync([NotNull] BaseContext context) @@ -79,15 +99,21 @@ namespace OpenIddict.Server.Owin throw new ArgumentNullException(nameof(context)); } - return new ValueTask(_options.CurrentValue.EnableLogoutEndpointPassthrough); + return new ValueTask(_options.CurrentValue.EnableLogoutEndpointCaching); } } /// - /// Represents a filter that excludes the associated handlers if no OWIN request can be found. + /// Represents a filter that excludes the associated handlers if the + /// pass-through mode was not enabled for the logout endpoint. /// - public class RequireOwinRequest : IOpenIddictServerHandlerFilter + public class RequireLogoutEndpointPassthroughEnabled : IOpenIddictServerHandlerFilter { + private readonly IOptionsMonitor _options; + + public RequireLogoutEndpointPassthroughEnabled([NotNull] IOptionsMonitor options) + => _options = options; + public ValueTask IsActiveAsync([NotNull] BaseContext context) { if (context == null) @@ -95,20 +121,15 @@ namespace OpenIddict.Server.Owin throw new ArgumentNullException(nameof(context)); } - return new ValueTask(context.Transaction.GetOwinRequest() != null); + return new ValueTask(_options.CurrentValue.EnableLogoutEndpointPassthrough); } } /// - /// Represents a filter that excludes the associated handlers if the HTTPS requirement was disabled. + /// Represents a filter that excludes the associated handlers if no OWIN request can be found. /// - public class RequireTransportSecurityRequirementEnabled : IOpenIddictServerHandlerFilter + public class RequireOwinRequest : IOpenIddictServerHandlerFilter { - private readonly IOptionsMonitor _options; - - public RequireTransportSecurityRequirementEnabled([NotNull] IOptionsMonitor options) - => _options = options; - public ValueTask IsActiveAsync([NotNull] BaseContext context) { if (context == null) @@ -116,18 +137,18 @@ namespace OpenIddict.Server.Owin throw new ArgumentNullException(nameof(context)); } - return new ValueTask(!_options.CurrentValue.DisableTransportSecurityRequirement); + return new ValueTask(context.Transaction.GetOwinRequest() != null); } } /// - /// Represents a filter that excludes the associated handlers if request caching was not enabled. + /// Represents a filter that excludes the associated handlers if the HTTPS requirement was disabled. /// - public class RequireRequestCachingEnabled : IOpenIddictServerHandlerFilter + public class RequireTransportSecurityRequirementEnabled : IOpenIddictServerHandlerFilter { private readonly IOptionsMonitor _options; - public RequireRequestCachingEnabled([NotNull] IOptionsMonitor options) + public RequireTransportSecurityRequirementEnabled([NotNull] IOptionsMonitor options) => _options = options; public ValueTask IsActiveAsync([NotNull] BaseContext context) @@ -137,7 +158,7 @@ namespace OpenIddict.Server.Owin throw new ArgumentNullException(nameof(context)); } - return new ValueTask(_options.CurrentValue.EnableRequestCaching); + return new ValueTask(!_options.CurrentValue.DisableTransportSecurityRequirement); } } diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs index 6bd2cc55..17eaa4de 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Authentication.cs @@ -80,7 +80,7 @@ namespace OpenIddict.Server.Owin public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(ExtractGetOrPostRequest.Descriptor.Order + 1_000) .Build(); @@ -167,7 +167,7 @@ namespace OpenIddict.Server.Owin public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(RestoreCachedRequestParameters.Descriptor.Order + 1_000) .Build(); @@ -222,7 +222,7 @@ namespace OpenIddict.Server.Owin // Note: the cache key is always prefixed with a specific marker // to avoid collisions with the other types of cached payloads. await _cache.SetAsync(Cache.AuthorizationRequest + context.Request.RequestId, - stream.ToArray(), _options.CurrentValue.RequestCachingPolicy); + stream.ToArray(), _options.CurrentValue.AuthorizationEndpointCachingPolicy); // Create a new GET authorization request containing only the request_id parameter. var address = WebUtilities.AddQueryString( @@ -261,7 +261,7 @@ namespace OpenIddict.Server.Owin public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(ProcessFormPostResponse.Descriptor.Order - 1_000) .Build(); diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs index 2d3e2ef1..f02f01c9 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.Session.cs @@ -79,7 +79,7 @@ namespace OpenIddict.Server.Owin public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(ExtractGetOrPostRequest.Descriptor.Order + 1_000) .Build(); @@ -166,7 +166,7 @@ namespace OpenIddict.Server.Owin public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(RestoreCachedRequestParameters.Descriptor.Order + 1_000) .Build(); @@ -221,7 +221,7 @@ namespace OpenIddict.Server.Owin // Note: the cache key is always prefixed with a specific marker // to avoid collisions with the other types of cached payloads. await _cache.SetAsync(Cache.LogoutRequest + context.Request.RequestId, - stream.ToArray(), _options.CurrentValue.RequestCachingPolicy); + stream.ToArray(), _options.CurrentValue.LogoutEndpointCachingPolicy); // Create a new GET logout request containing only the request_id parameter. var address = WebUtilities.AddQueryString( @@ -260,7 +260,7 @@ namespace OpenIddict.Server.Owin public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .AddFilter() + .AddFilter() .UseSingletonHandler() .SetOrder(ProcessQueryResponse.Descriptor.Order - 1_000) .Build(); diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinOptions.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinOptions.cs index a41c7b98..bfb8de6c 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinOptions.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinOptions.cs @@ -79,19 +79,33 @@ namespace OpenIddict.Server.Owin public bool EnableVerificationEndpointPassthrough { get; set; } /// - /// Gets or sets a boolean indicating whether request caching should be enabled. - /// When enabled, both authorization and logout requests are automatically stored + /// Gets or sets a boolean indicating whether requests received by the authorization endpoint + /// should be cached. When enabled, authorization requests are automatically stored /// in the distributed cache, which allows flowing large payloads across requests. /// Enabling this option is recommended when using external authentication providers /// or when large GET or POST OpenID Connect authorization requests support is required. /// - public bool EnableRequestCaching { get; set; } + public bool EnableAuthorizationEndpointCaching { get; set; } /// - /// Gets or sets the caching policy used to determine how long the authorization - /// and end session requests should be cached by the distributed cache implementation. + /// Gets or sets a boolean indicating whether requests received by the logout endpoint should be cached. + /// When enabled, authorization requests are automatically stored in the distributed cache. /// - public DistributedCacheEntryOptions RequestCachingPolicy { get; set; } = new DistributedCacheEntryOptions + public bool EnableLogoutEndpointCaching { get; set; } + + /// + /// Gets or sets the caching policy used by the authorization endpoint. + /// + public DistributedCacheEntryOptions AuthorizationEndpointCachingPolicy { get; set; } = new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1), + SlidingExpiration = TimeSpan.FromMinutes(30) + }; + + /// + /// Gets or sets the caching policy used by the logout endpoint. + /// + public DistributedCacheEntryOptions LogoutEndpointCachingPolicy { get; set; } = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1), SlidingExpiration = TimeSpan.FromMinutes(30)