From e53a723766c3ba9cb60d24afb86bbcb428e7066b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Tue, 11 Jul 2023 14:53:49 +0200 Subject: [PATCH] Enable the "plain" code challenge method by default to increase interoperability --- ...IddictClientWebIntegrationConfiguration.cs | 24 +++++++------- .../OpenIddictClientBuilder.cs | 2 ++ .../OpenIddictServerBuilder.cs | 2 ++ ...ctServerIntegrationTests.Authentication.cs | 33 +++++-------------- 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationConfiguration.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationConfiguration.cs index 4502a3a2..98073b11 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationConfiguration.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationConfiguration.cs @@ -6,7 +6,6 @@ using System.ComponentModel; using System.Net.Http; -using System.Security.Cryptography.X509Certificates; using Microsoft.Extensions.Http; using Microsoft.Extensions.Options; using OpenIddict.Client.SystemNetHttp; @@ -61,16 +60,19 @@ public sealed partial class OpenIddictClientWebIntegrationConfiguration : IConfi options.UnfilteredHttpClientHandlerActions.Add(static (registration, handler) => { - // Note: while not enforced yet, Pro Santé Connect's specification requires sending a TLS - // client certificate when communicating with its backchannel OpenID Connect endpoints. - // - // For that, the primary HTTP handler must be altered or replaced by an instance that - // includes the client certificate set in the options in its certificate collection. - // - // For more information, see EXI PSC 24 in the annex part of - // https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000045551195. - if (registration.ProviderType is ProviderTypes.ProSantéConnect && - registration.GetProSantéConnectSettings() is { ClientCertificate: X509Certificate2 certificate }) + var certificate = registration.ProviderType switch + { + // Note: while not enforced yet, Pro Santé Connect's specification requires sending a TLS + // client certificate when communicating with its backchannel OpenID Connect endpoints. + // + // For more information, see EXI PSC 24 in the annex part of + // https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000045551195. + ProviderTypes.ProSantéConnect => registration.GetProSantéConnectSettings().ClientCertificate, + + _ => null + }; + + if (certificate is not null) { handler.ClientCertificates.Add(certificate); handler.ClientCertificateOptions = ClientCertificateOption.Manual; diff --git a/src/OpenIddict.Client/OpenIddictClientBuilder.cs b/src/OpenIddict.Client/OpenIddictClientBuilder.cs index 45d816cb..452b12c1 100644 --- a/src/OpenIddict.Client/OpenIddictClientBuilder.cs +++ b/src/OpenIddict.Client/OpenIddictClientBuilder.cs @@ -898,6 +898,7 @@ public sealed class OpenIddictClientBuilder public OpenIddictClientBuilder AllowAuthorizationCodeFlow() => Configure(options => { + options.CodeChallengeMethods.Add(CodeChallengeMethods.Plain); options.CodeChallengeMethods.Add(CodeChallengeMethods.Sha256); options.GrantTypes.Add(GrantTypes.AuthorizationCode); @@ -934,6 +935,7 @@ public sealed class OpenIddictClientBuilder public OpenIddictClientBuilder AllowHybridFlow() => Configure(options => { + options.CodeChallengeMethods.Add(CodeChallengeMethods.Plain); options.CodeChallengeMethods.Add(CodeChallengeMethods.Sha256); options.GrantTypes.Add(GrantTypes.AuthorizationCode); diff --git a/src/OpenIddict.Server/OpenIddictServerBuilder.cs b/src/OpenIddict.Server/OpenIddictServerBuilder.cs index 66fb2dc7..ee309f89 100644 --- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs +++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs @@ -882,6 +882,7 @@ public sealed class OpenIddictServerBuilder public OpenIddictServerBuilder AllowAuthorizationCodeFlow() => Configure(options => { + options.CodeChallengeMethods.Add(CodeChallengeMethods.Plain); options.CodeChallengeMethods.Add(CodeChallengeMethods.Sha256); options.GrantTypes.Add(GrantTypes.AuthorizationCode); @@ -934,6 +935,7 @@ public sealed class OpenIddictServerBuilder public OpenIddictServerBuilder AllowHybridFlow() => Configure(options => { + options.CodeChallengeMethods.Add(CodeChallengeMethods.Plain); options.CodeChallengeMethods.Add(CodeChallengeMethods.Sha256); options.GrantTypes.Add(GrantTypes.AuthorizationCode); diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs index da782657..ca4ddd27 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs @@ -943,10 +943,16 @@ public abstract partial class OpenIddictServerIntegrationTests } [Fact] - public async Task ValidateAuthorizationRequest_RequestIsRejectedWhenCodeChallengeMethodIsMissing() + public async Task ValidateAuthorizationRequest_RequestIsRejectedWhenCodeChallengeMethodIsMissingAndPlainIsNotSupported() { // Arrange - await using var server = await CreateServerAsync(options => options.EnableDegradedMode()); + await using var server = await CreateServerAsync(options => + { + options.EnableDegradedMode(); + options.Services.PostConfigure(options => + options.CodeChallengeMethods.Remove(CodeChallengeMethods.Plain)); + }); + await using var client = await server.CreateClientAsync(); // Act @@ -994,29 +1000,6 @@ public abstract partial class OpenIddictServerIntegrationTests Assert.Equal(SR.FormatID8000(SR.ID2032), response.ErrorUri); } - [Fact] - public async Task ValidateAuthorizationRequest_RequestIsRejectedWhenPlainCodeChallengeMethodIsNotExplicitlyEnabled() - { - // Arrange - await using var server = await CreateServerAsync(options => options.EnableDegradedMode()); - await using var client = await server.CreateClientAsync(); - - // Act - var response = await client.PostAsync("/connect/authorize", new OpenIddictRequest - { - ClientId = "Fabrikam", - CodeChallenge = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM", - CodeChallengeMethod = CodeChallengeMethods.Plain, - RedirectUri = "http://www.fabrikam.com/path", - ResponseType = ResponseTypes.Code - }); - - // Assert - Assert.Equal(Errors.InvalidRequest, response.Error); - Assert.Equal(SR.FormatID2032(Parameters.CodeChallengeMethod), response.ErrorDescription); - Assert.Equal(SR.FormatID8000(SR.ID2032), response.ErrorUri); - } - [Theory] [InlineData(CodeChallengeMethods.Plain)] [InlineData(CodeChallengeMethods.Sha256)]