Browse Source

Enable the "plain" code challenge method by default to increase interoperability

pull/1825/head
Kévin Chalet 3 years ago
parent
commit
e53a723766
  1. 24
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationConfiguration.cs
  2. 2
      src/OpenIddict.Client/OpenIddictClientBuilder.cs
  3. 2
      src/OpenIddict.Server/OpenIddictServerBuilder.cs
  4. 33
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Authentication.cs

24
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;

2
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);

2
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);

33
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<OpenIddictServerOptions>(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)]

Loading…
Cancel
Save