Swashbuckle.AspNetCore icon indicating copy to clipboard operation
Swashbuckle.AspNetCore copied to clipboard

Cannot offer both AuthorizationCode PKCE and Client Credentials

Open sprudel79 opened this issue 2 years ago • 7 comments

Hi everyone, I am using latest Swashbuckle version 6.4.0. For my service which is using IdentityServer as IDP I would like to offer both authorization code with PKCE based authentication as well as client credentials in Swagger. I should say that both auth options work perfectly when I enable them individually. As I am aware to make PKCE working I need to call this here:

app.UseSwaggerUI(
                options =>
                {
                    options.OAuthUsePkce();                                                                  
                });

Now I would like to offer client credentials authorization as well, but when the call to OAuthUsePkce is there, the "client_secret" field which is required for client credentials disappears:

image

How can I bring back the client_secret field without having to disable PKCE?

Thanks in advance.

sprudel79 avatar Jul 27 '22 16:07 sprudel79

We have exactly the same problem. 😢 Due to that, we can´t update any more to the latest versions. Please... is it possible to correct this?

tiagofe avatar Oct 04 '22 07:10 tiagofe

Same issue - seems its fixed in this PR - https://github.com/swagger-api/swagger-ui/pull/8146

shamnani-kamlesh avatar Oct 31 '22 10:10 shamnani-kamlesh

Better still - it's also fixed for the auth code flow in swagger-api/swagger-ui#8268

Pilchard123 avatar Nov 11 '22 13:11 Pilchard123

Happy to upgrade the related swagger-ui bits once the above changes have been released there. Feel free to ping me with a reminder when that happens

domaindrivendev avatar Nov 14 '22 14:11 domaindrivendev

@domaindrivendev It appears to already have been released in 4.15.3.

Pilchard123 avatar Nov 14 '22 23:11 Pilchard123

Thanks everyone involved, I will check the changes soon and will comment here the status.

sprudel79 avatar Nov 15 '22 07:11 sprudel79

Hi everyone, the latest stable Swashbuckle.AspNetCore version (6.4.0) relies on swagger-ui-dist 4.14.0 which of course doesn't include the fix from 4.15.3. Is it possible to create a new release with the updated swagger-ui-dist version? Thank you.

sprudel79 avatar Nov 22 '22 15:11 sprudel79

We need a new distribution as @sprudel79 mentions.

markwalsh-liverpool avatar Jan 13 '23 10:01 markwalsh-liverpool

There was just a recent update a few days back. I have upgraded my local setup and have tested the issue. First of all the latest Swashbuckle.AspNetCore version (6.5.0) uses now swagger-ui-dist 4.15.5. When I run my updated setup locally I can see finally the client_secret field for the clientCredentials flow. Thanks for fixing the issue!

sprudel79 avatar Jan 13 '23 13:01 sprudel79

@sprudel79 it appears i have the opposite problem? I am using PKCE auth and do not want the client_secret field shown. after upgrading to 6.5.0 it now shows. is there a way to force it to be hidden?

aherrick avatar Jan 16 '23 14:01 aherrick

Hi @aherrick, if you really need to hide the client_secret field you could perhaps try the SwaggerUI options "InjectStylesheet" or "InjectJavascript" to apply the necessary logic.

sprudel79 avatar Jan 17 '23 13:01 sprudel79

@sprudel79 Can you share your configuration? Are you using pkce?

markwalsh-liverpool avatar Jan 17 '23 14:01 markwalsh-liverpool

Here we go @markwalsh-liverpool, I can share a code snippet (which should show the idea) of the Swagger usage with both PKCE and ClientCredentials:

public virtual void ConfigureServices(IServiceCollection services)
{
    ...
    _ = services.AddSwaggerGen(options =>
    {
        ...
      
        var flows = new OpenApiOAuthFlows();

        flows.AuthorizationCode = new OpenApiOAuthFlow
        {
            AuthorizationUrl = new Uri(baseUrlIdentityServer + "/connect/authorize"),
            TokenUrl = new Uri(baseUrlIdentityServer + "/connect/token"),
            Scopes = new Dictionary<string, string>
            {
                { "MyAPI", string.Empty },
                { "openid", string.Empty },
                { "email", string.Empty },
                { "profile",string.Empty}
            }
        };

        flows.ClientCredentials = new OpenApiOAuthFlow
        {
            TokenUrl = new Uri(baseUrlIdentityServer + "/connect/token"),
            Scopes = new Dictionary<string, string>
            {
                { "MyAPI", string.Empty }
            }
        };

        options.AddSecurityDefinition("IdentityServer", new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference
            {
                Type = ReferenceType.SecurityScheme,
                Id = "IdentityServer"
            },
            In = ParameterLocation.Header,
            Name = "Bearer",
            Scheme = "oauth2",
            Type = SecuritySchemeType.OAuth2,
            Flows = flows
        });

        options.AddSecurityRequirement(new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference=new OpenApiReference{Type=ReferenceType.SecurityScheme,Id="IdentityServer"},
                    Scheme="oauth2",
                    Name="Bearer",
                    In=ParameterLocation.Header
                },
                new List<string>{"openid","email","profile","MyAPI"}
            }
        });
        
        ...
    });

    ...
}

public virtual void Configure(IApplicationBuilder app, IHostApplicationLifetime applicationLifetime)
{
    ...
    _ = app.UseSwagger(o =>
    {
    });

    if (ServiceOptions.Swagger.UseSwaggerUI)
    {
        var apiVersionDescriptionProvider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();
        
        _ = app.UseSwaggerUI(options =>
        {
            options.OAuthUsePkce();

            foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
            {
                options.SwaggerEndpoint($"{baseUrlMyAPI}/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
            }
        });
    }
    ...
}

sprudel79 avatar Jan 17 '23 14:01 sprudel79