简体   繁体   中英

How do I configure SwaggerGen with OpenIddict parameters for client credentials grant?

I'm trying to figure out how I can configure SwaggerGen to populate/display the fields/parameters for OpenIddict and client credentials grant.

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", UriKind.Relative), 
                Scopes = new Dictionary<string, string>()
                {

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

It's displaying the Authorize button but when I click it, it opens an empty modal like shown in the below image:

在此处输入图像描述

Appreciate anyone who can point me at some docs that would explain what I need to configure in services.AddSwaggerGen() to get this configured so we can easily test our API through the interactive documentation generated by Swagger.

You need to specify a couple more options when defining an OpenApiSecurityScheme .

Here's how you can go about setting it up:

  • Specify TokenUrl . Client credentials flow works on /token endpoint, so we have to give it a correct URL. Here I've used IdentityServer's demo server
  • Specify how the token will be sent to the backend: We want it to be sent in Authorization header with Bearer scheme.
  • Specify which scopes the application needs. This is a dictionary that maps scope -> description.
  • Finally, add a security requirement (here it's for all endpoints) that will show a lock icon next to the endpoint. (That also helps other OpenAPI clients during code generation)
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" }
                    }
                }
            );
        }
    );
}

Here's how it looks when it's all set up:

身份验证弹出

Once you authenticate, it gets filled with the token:

我们拿到了令牌

Now we can send requests, and Swagger UI includes the token in the headers as we'd expect:

示例请求

Prefilling auth popup

As a finishing touch, we can pre-populate the auth dialog with some default values:

Inside the Startup:Configure methods where we set up the Swagger UI we can specify client id + secret (which defeats the purpose, but could prove useful in local development)

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

Reference

You need to configure swagger to discover the OpenIddict configuration. See code sample below:

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 = HeaderNames.Authorization,
        Flows = new OpenApiOAuthFlows
        {
            ClientCredentials = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new Uri("/connect/token", UriKind.Relative), 
                TokenUrl = new Uri("/connect/token", UriKind.Relative)
            }
        },
        OpenIdConnectUrl = new Uri("/.well-known/openid-configuration", UriKind.Relative)
    });

    options.AddSecurityRequirement(
                        new OpenApiSecurityRequirement
                        {
                            {
                                new OpenApiSecurityScheme
                                {
                                    Reference = new OpenApiReference
                                        { Type = ReferenceType.SecurityScheme, Id = "oauth" },
                                },
                                Array.Empty<string>()
                            }
                        }
                    );

});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM