如何使用 OpenIddict 参数为客户端凭据授予配置 SwaggerGen?

问题描述

我想弄清楚如何配置 SwaggerGen 以填充/显示 OpenIddict 和客户端凭据授予的字段/参数。

services.AddDbContext<AppDbContext>(options =>
{
    options.UsesqlServer(Configuration.GetConnectionString("DefaultConnection"));
    options.USEOpenIddict();
});

services.AddOpenIddict()
    .AddCore(options =>
    {
        // Configure OpenIddict to use the Entity Framework Core stores and models.
        // Note: call ReplaceDefaultEntities() to replace the default entities.
        options.UseEntityFrameworkCore().UseDbContext<AppDbContext>();
    })
    .AddServer(options =>
    {
        // Enable the token endpoint.
        options.SetTokenEndpointUris("/connect/token");

        // Enable the client credentials flow.
        options.AllowClientCredentialsFlow();

        // Register the signing and encryption credentials.
        options.AddDevelopmentEncryptionCertificate()
              .AddDevelopmentSigningCertificate();

        // Register the ASP.NET Core host and configure the ASP.NET Core options.
        options.UseAspNetCore()
              .EnabletokenEndpointPassthrough();
    })
    .AddValidation(options =>
    {
        // Import the configuration from the local OpenIddict server instance.
        options.UseLocalServer();

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

services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1",new OpenApiInfo { Title = "PCM",Version = "v1" });
    options.AddSecurityDeFinition("Authentication",new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OpenIdConnect,Description = "Description",In = ParameterLocation.Header,Name = "Notsure",Flows = new OpenApiOAuthFlows
        {
            ClientCredentials = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new Uri("/connect/token",UriKind.Relative),TokenUrl = new Uri("/connect/token",Scopes = new Dictionary<string,string>()
                {

                }
            }
        },OpenIdConnectUrl = new Uri("/connect/authorize",UriKind.Relative)
    });
});

它正在显示授权按钮,但当我点击它时,它会打开一个空的模式,如下图所示:

enter image description here

感谢任何能指出我需要在 services.AddSwaggerGen() 中配置的文档以进行配置的人,以便我们可以通过 Swagger 生成的交互式文档轻松测试我们的 API。

解决方法

在定义 OpenApiSecurityScheme 时,您需要指定更多选项。

您可以通过以下方式进行设置:

  • 指定 TokenUrl。客户端凭据流适用于 /token 端点,因此我们必须为其提供正确的 URL。这里我使用了 IdentityServer 的 demo server
  • 指定令牌将如何发送到后端:我们希望它以 Authorization 方案在 Bearer 标头中发送。
  • 指定应用程序需要的范围。这是一个映射范围 -> 描述的字典。
  • 最后,添加一个安全要求(此处适用于所有端点),该要求将在端点旁边显示一个锁定图标。 (这也有助于其他 OpenAPI 客户端在代码生成过程中)
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddSwaggerGen(
        c =>
        {
            c.SwaggerDoc("v1",new OpenApiInfo { Title = "ApiPlayground",Version = "v1" });
            c.AddSecurityDefinition(
                "oauth",new OpenApiSecurityScheme
                {
                    Flows = new OpenApiOAuthFlows
                    {
                        ClientCredentials = new OpenApiOAuthFlow
                        {
                            Scopes = new Dictionary<string,string>
                            {
                                ["api"] = "api scope description"
                            },TokenUrl = new Uri("https://demo.identityserver.io/connect/token"),},In = ParameterLocation.Header,Name = HeaderNames.Authorization,Type = SecuritySchemeType.OAuth2
                }
            );
            c.AddSecurityRequirement(
                new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                                { Type = ReferenceType.SecurityScheme,Id = "oauth" },new[] { "api" }
                    }
                }
            );
        }
    );
}

以下是设置完成后的样子:

auth popup

一旦您进行身份验证,它就会充满令牌:

we got the token

现在我们可以发送请求,Swagger UI 如我们所期望的那样在标头中包含令牌:

example request

预填充身份验证弹出窗口

最后,我们可以用一些默认值预填充 auth 对话框:

在设置 Swagger UI 的 Startup:Configure 方法中,我们可以指定客户端 ID + 密码(这违背了目的,但在本地开发中可能会证明有用)

app.UseSwaggerUI(c => {
    c.SwaggerEndpoint("/swagger/v1/swagger.json","ApiPlayground v1");
    c.OAuthClientId("m2m");
    c.OAuthClientSecret("secret");
});

参考