OpenIddict 缺少必需的 'code_challenge' 参数

The mandatory 'code_challenge' parameter is missing with OpenIddict

我有一个身份服务器 运行 asp.net core 5, with openiddict 3.1.1 我在从 openiddict 收到错误的地方遇到了问题:

error:invalid_request error_description:The mandatory 'code_challenge' parameter is missing. error_uri:https://documentation.openiddict.com/errors/ID2029

在某些情况下,但不是全部。我的身份服务器有一个 startup.cs 的:

services.AddDbContext<IdentityContext>(options =>
        {
            options.UseSqlServer(dbConnectionString, x => x.UseNetTopologySuite());
            // Register the entity sets needed by OpenIddict.
            // Note: use the generic overload if you need
            // to replace the default OpenIddict entities.
            options.UseOpenIddict<Guid>();
        });

        services.AddTransient<IPasswordHasher<ApplicationUser>, CustomPasswordHasher>();
        services.AddTransient<IOptions<IdentityOptions>, CustomOptions>();
        services.AddScoped<SignInManager<ApplicationUser>, CustomSignInManager>();

        services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<IdentityContext>()
                //.AddDefaultUI()
                .AddDefaultTokenProviders();


        services.AddOpenIddict()

    // Register the OpenIddict core components.
    .AddCore(options =>
    {
        // Configure OpenIddict to use the Entity Framework Core stores and models.
        // Note: call ReplaceDefaultEntities() to replace the default entities.
        options.UseEntityFrameworkCore()
               .UseDbContext<IdentityContext>()
               .ReplaceDefaultEntities<Guid>();
    })

    // Register the OpenIddict server components.
    .AddServer(options =>
    {
        // Enable the authorization, device, logout, token, userinfo and verification endpoints.
        options.SetAuthorizationEndpointUris("/connect/authorize")
               .SetLogoutEndpointUris("/connect/signout")
               .SetTokenEndpointUris("/connect/token");

        // Enable the client credentials flow.
        options
        .AllowAuthorizationCodeFlow().RequireProofKeyForCodeExchange()
        .AllowRefreshTokenFlow();

        // Encryption and signing of tokens
        options
            .AddEphemeralEncryptionKey()
            .AddEphemeralSigningKey()
            .DisableAccessTokenEncryption();    //TODO: not a huge deal as long as we're not hiding anything bad here.

        // Expose all the supported claims in the discovery document.
        options.RegisterClaims(Configuration.GetSection("OpenIddict:Claims").Get<string[]>());

        // Expose all the supported scopes in the discovery document.
        options.RegisterScopes(Configuration.GetSection("OpenIddict:Scopes").Get<string[]>());

        // Register the ASP.NET Core host and configure the ASP.NET Core-specific options.
        options.UseAspNetCore()
               .EnableStatusCodePagesIntegration()
               .EnableAuthorizationEndpointPassthrough()
                .EnableAuthorizationRequestCaching()
               .EnableLogoutEndpointPassthrough()
               .EnableVerificationEndpointPassthrough()
               .EnableTokenEndpointPassthrough();
    })

    // Register the OpenIddict validation components.
    .AddValidation(options =>
    {
        // Import the configuration from the local OpenIddict server instance.
        options.UseLocalServer();

        // Register the ASP.NET Core host.
        options.UseAspNetCore();

        // Enable authorization entry validation, which is required to be able
        // to reject access tokens retrieved from a revoked authorization code.
        options.EnableAuthorizationEntryValidation();
    });

OpenIDWorker 为:

public async Task StartAsync(CancellationToken cancellationToken)
    {
        using IServiceScope scope = _serviceProvider.CreateScope();

        IdentityContext context = scope.ServiceProvider.GetRequiredService<IdentityContext>();

        await RegisterApplicationsAsync(scope.ServiceProvider, _configuration);

        static async Task RegisterApplicationsAsync(IServiceProvider provider, IConfiguration configuration)
        {
            IOpenIddictApplicationManager manager = provider.GetRequiredService<IOpenIddictApplicationManager>();
            string clientID = configuration.GetSection("OpenIddict:ClientId").Get<string>();

            string clientSecretString = "blahblahblah";
            if (await manager.FindByClientIdAsync(clientID) is null)
            {
                await manager.CreateAsync(new OpenIddictApplicationDescriptor
                {
                    ClientId = clientID,
                    ClientSecret = clientSecretString,
                    ConsentType = ConsentTypes.Explicit,
                    DisplayName = configuration.GetSection("OpenIddict:DisplayName").Get<string>(),
                    PostLogoutRedirectUris =
{
    new Uri("https://localhost:44330/signout-callback-oidc")
},
                    RedirectUris =
{
    new Uri("https://localhost:44330/signin-oidc")
},
                    Permissions =
                {
                    Permissions.Endpoints.Authorization,
                    Permissions.Endpoints.Logout,
                    Permissions.Endpoints.Token,
                    Permissions.GrantTypes.AuthorizationCode,
                    Permissions.GrantTypes.RefreshToken,
                    Permissions.ResponseTypes.Code,
                    Permissions.Scopes.Email,
                    Permissions.Scopes.Profile,
                    Permissions.Scopes.Roles,
                },
                    Requirements =
                {
                    Requirements.Features.ProofKeyForCodeExchange
                }
                });
            }
        }

    }

当我尝试使用具有以下 startup.cs 的 C# razor 应用程序连接到服务器时,它工作正常并且 w/out 有任何问题:

string clientSecretString = "blahblahblah";
        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        }).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
         {
             options.LoginPath = "/login";
             options.ExpireTimeSpan = TimeSpan.FromMinutes(50);
             options.SlidingExpiration = false;
         })

        .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
        {
            // Note: these settings must match the application details
            // inserted in the database at the server level.
            options.ClientId = Configuration.GetSection("ClientId").Get<string>();
            options.ClientSecret = clientSecretString;

            options.RequireHttpsMetadata = false;
            options.GetClaimsFromUserInfoEndpoint = true;
            options.SaveTokens = true;

            // Use the authorization code flow.
            options.ResponseType = OpenIdConnectResponseType.Code;
            options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;

            // Note: setting the Authority allows the OIDC client middleware to automatically
            // retrieve the identity provider's configuration and spare you from setting
            // the different endpoints URIs or the token validation parameters explicitly.

            options.Authority = "https://localhost:44330/";

            options.Scope.Add("email");
            options.Scope.Add("roles");
            options.Scope.Add("offline_access");

            options.SecurityTokenValidator = new JwtSecurityTokenHandler
            {
                // Disable the built-in JWT claims mapping feature.
                InboundClaimTypeMap = new Dictionary<string, string>()
            };

            options.TokenValidationParameters.NameClaimType = "name";
            options.TokenValidationParameters.RoleClaimType = "role";

            options.AccessDeniedPath = "/";
        });

但是当我尝试使用 https://oidcdebugger.com/, or if I try to connect to it using Azure B2C user flows, I get the error message above about missing a code_challenge (see image 连接到它时)

我在这里错过了什么?我的计划是使用 B2C,但我没有看到什么阻碍了我。

参考https://github.com/openiddict/openiddict-core/issues/1361。问题最终成为 B2C 本身的问题,需要对其进行修复