swagger-api / swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.
https://swagger.io
Apache License 2.0
26.63k stars 8.96k forks source link

Oauth2 Client Credentials : Allow to pass client_id and client_secret via the body instead of authrorization header (needed for Azure AD B2C) #10190

Open corentinvds opened 3 weeks ago

corentinvds commented 3 weeks ago

Content & configuration

Swagger/OpenAPI definition:

 "securitySchemes": {
            "Azure AD B2C": {
                "type": "oauth2",
                "description": "Use this scheme to get an access token from Azure AD B2C for your application.",
                "flows": {
                    "clientCredentials": {
                        "tokenUrl": "https://my-tenant.b2clogin.com/my-tenant.onmicrosoft.com/oauth2/v2.0/token?p=MY-POLICY",
                        "scopes": {
                            "https://my-tenant.onmicrosoft.com/my-app/.default": "Get default scopes for the client"
                        }
                    },
                }
            }

Is your feature request related to a problem?

I cannot make the Swagger UI work with the OAuth2 client credentials flow implemented by Azure AD B2C. Swagger UI sends the client_id and client_secret via the Authorization: Basic XXXXXXXX header, which is not supported here.

Here an example of the error with the basic auth:

curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Authorization=Basic XXXXXXX="\
  -d 'scope=https%3A%2F%2Fmy-tenant.onmicrosoft.com%2Fmy-app%2F.default&grant_type=client_credentials' 'https://my-tenant.b2clogin.com/my-tenant.onmicrosoft.com/oauth2/v2.0/token?p=MY-POLICY'

{"error":"invalid_client","error_description":"AADB2C90008: The request does not contain a client id parameter.\r\nCorrelation ID: XXXXXXX\r\nTimestamp: 2024-11-XX XX:XX:XXZ\r\n"}

Here is a working example:

curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'client_id=MY_CLIENT_ID&client_secret=MY_CLIENT_SECRET&scope=https%3A%2F%2Fmy-tenant.onmicrosoft.com%2Fmy-app%2F.default&grant_type=client_credentials' 'https://my-tenant.b2clogin.com/my-tenant.onmicrosoft.com/oauth2/v2.0/token?p=MY-POLICY'

In Swagger UI, I could not find a way to change the current behavior. I use a swagger.json file with the Swagger UI docker image.

Describe the solution you'd like

It would be nice to have the choice to send the credentials either via the header or via the body.

I found out that a similar solution has already been implemented for the password flow : issue #4192, PR https://github.com/swagger-api/swagger-ui/pull/4213/files. Would it be possible to have the same principle here ?

Describe alternatives you've considered

I found several issues and SO questions about this proposing to either implement an interceptor in the application that is serving the swagger app or rewrite a part of the Swagger UI javascript code.

The first one is not possible since I use a static swagger.json file and I want to avoid the second one since I use the Swagger UI docker image out of the box.

For now, the only workaround I have is to get the token via a bash script and copy it into the Swagger UI Bearer authentication form. Since I want to use this swagger as a self-explaining documentation of my API for third parties, this is not ideal.

Additional context

I found this issue related to the same problem #4905. It states that Swagger UI implements the standard and recommended method but it would be nice to have the possibility to support both use cases.