From cf0e49a3b85fdebff8e57edb86a30a701b9284e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Thu, 3 Mar 2022 19:50:30 +0100 Subject: [PATCH] Use Uri.OriginalString for issuer comparison --- .../OpenIddictClientHandlers.Protection.cs | 2 +- .../OpenIddictClientHandlers.Userinfo.cs | 17 ++++++++++++----- .../OpenIddictClientHandlers.cs | 6 +++--- ...nIddictValidationServerIntegrationBuilder.cs | 2 +- ...dictValidationServerIntegrationExtensions.cs | 4 ++-- ...penIddictValidationHandlers.Introspection.cs | 17 +++++++++++++---- .../OpenIddictValidationHandlers.Protection.cs | 2 +- 7 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs index 6a98612a..df755fef 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs @@ -110,7 +110,7 @@ public static partial class OpenIddictClientHandlers var parameters = registration!.TokenValidationParameters.Clone(); - parameters.ValidIssuer ??= configuration.Issuer?.AbsoluteUri ?? registration.Issuer?.AbsoluteUri; + parameters.ValidIssuer ??= configuration.Issuer?.OriginalString; parameters.ValidateIssuer = !string.IsNullOrEmpty(parameters.ValidIssuer); // Combine the signing keys registered statically in the token validation parameters diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.Userinfo.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.Userinfo.cs index e2150491..0ee86817 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.Userinfo.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.Userinfo.cs @@ -97,7 +97,7 @@ public static partial class OpenIddictClientHandlers .Build(); /// - public ValueTask HandleAsync(HandleUserinfoResponseContext context) + public async ValueTask HandleAsync(HandleUserinfoResponseContext context) { if (context is null) { @@ -107,7 +107,16 @@ public static partial class OpenIddictClientHandlers // Ignore the response instance if a userinfo token was extracted. if (!string.IsNullOrEmpty(context.UserinfoToken)) { - return default; + return; + } + + var configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); + + // Ensure the issuer resolved from the configuration matches the expected value. + if (configuration.Issuer != context.Issuer) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0307)); } // Create a new claims-based identity using the same authentication type @@ -120,7 +129,7 @@ public static partial class OpenIddictClientHandlers // Resolve the issuer that will be attached to the claims created by this handler. // Note: at this stage, the optional issuer extracted from the response is assumed // to be valid, as it is guarded against unknown values by the ValidateIssuer handler. - var issuer = (string?) context.Response[Claims.Issuer] ?? context.Issuer?.AbsoluteUri ?? ClaimsIdentity.DefaultIssuer; + var issuer = (string?) context.Response[Claims.Issuer] ?? configuration.Issuer!.OriginalString; foreach (var parameter in context.Response.GetParameters()) { @@ -196,8 +205,6 @@ public static partial class OpenIddictClientHandlers context.Principal = new ClaimsPrincipal(identity); - return default; - static string GetClaimValueType(JsonValueKind kind) => kind switch { JsonValueKind.True or JsonValueKind.False => ClaimValueTypes.Boolean, diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.cs index d0050572..0a50834f 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.cs @@ -75,7 +75,7 @@ public static partial class OpenIddictClientHandlers ValidateRequiredUserinfoToken.Descriptor, ValidateUserinfoToken.Descriptor, ValidateUserinfoTokenWellknownClaims.Descriptor, - ValidateUserinfoTokenWellknownSubject.Descriptor, + ValidateUserinfoTokenSubject.Descriptor, /* * Challenge processing: @@ -2663,7 +2663,7 @@ public static partial class OpenIddictClientHandlers /// /// Contains the logic responsible of validating the subject claim contained in the userinfo token. /// - public class ValidateUserinfoTokenWellknownSubject : IOpenIddictClientHandler + public class ValidateUserinfoTokenSubject : IOpenIddictClientHandler { /// /// Gets the default descriptor definition assigned to this handler. @@ -2672,7 +2672,7 @@ public static partial class OpenIddictClientHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseSingletonHandler() + .UseSingletonHandler() .SetOrder(ValidateUserinfoTokenWellknownClaims.Descriptor.Order + 1_000) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); diff --git a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationBuilder.cs b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationBuilder.cs index f8ae3526..be160ea1 100644 --- a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationBuilder.cs +++ b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationBuilder.cs @@ -15,7 +15,7 @@ namespace Microsoft.Extensions.DependencyInjection; public class OpenIddictValidationServerIntegrationBuilder { /// - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// The services collection. public OpenIddictValidationServerIntegrationBuilder(IServiceCollection services) diff --git a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs index 7d0c5a5f..bd8b74be 100644 --- a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs +++ b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs @@ -22,7 +22,7 @@ public static class OpenIddictValidationServerIntegrationExtensions /// /// The services builder used by OpenIddict to register new services. /// This extension can be safely called multiple times. - /// The . + /// The . public static OpenIddictValidationServerIntegrationBuilder UseLocalServer(this OpenIddictValidationBuilder builder) { if (builder is null) @@ -47,7 +47,7 @@ public static class OpenIddictValidationServerIntegrationExtensions /// The services builder used by OpenIddict to register new services. /// The configuration delegate used to configure the validation services. /// This extension can be safely called multiple times. - /// The . + /// The . public static OpenIddictValidationBuilder UseLocalServer( this OpenIddictValidationBuilder builder, Action configuration) { diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs index 6def980c..6957ef36 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs @@ -351,13 +351,22 @@ public static partial class OpenIddictValidationHandlers .Build(); /// - public ValueTask HandleAsync(HandleIntrospectionResponseContext context) + public async ValueTask HandleAsync(HandleIntrospectionResponseContext context) { if (context is null) { throw new ArgumentNullException(nameof(context)); } + var configuration = await context.Options.ConfigurationManager.GetConfigurationAsync(default) ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0140)); + + // Ensure the issuer resolved from the configuration matches the expected value. + if (configuration is not null && configuration.Issuer != context.Issuer) + { + throw new InvalidOperationException(SR.GetResourceString(SR.ID0307)); + } + // Create a new claims-based identity using the same authentication type // and the name/role claims as the one used by IdentityModel for JWT tokens. var identity = new ClaimsIdentity( @@ -368,7 +377,9 @@ public static partial class OpenIddictValidationHandlers // Resolve the issuer that will be attached to the claims created by this handler. // Note: at this stage, the optional issuer extracted from the response is assumed // to be valid, as it is guarded against unknown values by the ValidateIssuer handler. - var issuer = (string?) context.Response[Claims.Issuer] ?? context.Issuer?.AbsoluteUri ?? ClaimsIdentity.DefaultIssuer; + var issuer = (string?) context.Response[Claims.Issuer] ?? + configuration?.Issuer?.OriginalString ?? + context.Issuer?.OriginalString ?? ClaimsIdentity.DefaultIssuer; foreach (var parameter in context.Response.GetParameters()) { @@ -444,8 +455,6 @@ public static partial class OpenIddictValidationHandlers context.Principal = new ClaimsPrincipal(identity); - return default; - static string GetClaimValueType(JsonValueKind kind) => kind switch { JsonValueKind.True or JsonValueKind.False => ClaimValueTypes.Boolean, diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs index 115ced33..9af9bbde 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs @@ -70,7 +70,7 @@ public static partial class OpenIddictValidationHandlers // Clone the token validation parameters and set the issuer using the value found in the // OpenID Connect server configuration (that can be static or retrieved using discovery). var parameters = context.Options.TokenValidationParameters.Clone(); - parameters.ValidIssuer ??= configuration.Issuer?.AbsoluteUri ?? context.Issuer?.AbsoluteUri; + parameters.ValidIssuer ??= configuration.Issuer?.OriginalString; parameters.ValidateIssuer = !string.IsNullOrEmpty(parameters.ValidIssuer); // Combine the signing keys registered statically in the token validation parameters