Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot offer both AuthorizationCode PKCE and Client Credentials #2470

Closed
sprudel79 opened this issue Jul 27, 2022 · 13 comments
Closed

Cannot offer both AuthorizationCode PKCE and Client Credentials #2470

sprudel79 opened this issue Jul 27, 2022 · 13 comments

Comments

@sprudel79
Copy link

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.

@tiagofe
Copy link

tiagofe commented Oct 4, 2022

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?

@shamnani-kamlesh
Copy link

Same issue - seems its fixed in this PR - swagger-api/swagger-ui#8146

@Pilchard123
Copy link

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

@domaindrivendev
Copy link
Owner

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

@Pilchard123
Copy link

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

@sprudel79
Copy link
Author

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

@sprudel79
Copy link
Author

sprudel79 commented Nov 22, 2022

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.

@markwalsh-liverpool
Copy link

We need a new distribution as @sprudel79 mentions.

@sprudel79
Copy link
Author

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!

@aherrick
Copy link

@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?

@sprudel79
Copy link
Author

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.

@markwalsh-liverpool
Copy link

markwalsh-liverpool commented Jan 17, 2023

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

@sprudel79
Copy link
Author

sprudel79 commented Jan 17, 2023

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());
            }
        });
    }
    ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants