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

OAuth ClientCredentials doesn't pass client_id and client_secret in request body. #9800

Closed
mattfrear opened this issue Apr 11, 2024 · 4 comments

Comments

@mattfrear
Copy link

mattfrear commented Apr 11, 2024

Q&A (please complete the following information)

  • OS: Windows
  • Browser: Firefox
  • Version: 124.0.2
  • Method of installation: dist folder
  • Swagger-UI version: v5.15.0
  • Swagger/OpenAPI version: 3.0.1

Content & configuration

Example Swagger/OpenAPI definition:

{
  "openapi": "3.0.1",
  "info": {
    "title": "Test Api",
    "description": "testy testy",
    "version": "v1"
  },
  "paths": {
    "/api/rating-unit": {
      "post": {
        "tags": [
          "Property"
        ],
        "summary": "Create a rating unit changed notification",
        "requestBody": {
          "description": "",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudEvent"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CloudEvent": {
        "required": [
          "data",
          "id",
          "source",
          "specversion",
          "subject",
          "time",
          "type"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Data"
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "5565db35-01a9-4596-b611-9b26d2210c6e"
          },
          "specversion": {
            "minLength": 1,
            "type": "string",
            "example": 1
          },
          "source": {
            "minLength": 1,
            "type": "string",
            "example": "/1/S1D200/ZA_RE_PROPERTY"
          },
          "subject": {
            "minLength": 1,
            "type": "string",
            "example": "NoticeOfChange"
          },
          "time": {
            "type": "string",
            "format": "date-time"
          },
          "type": {
            "minLength": 1,
            "type": "string",
            "example": "sap.s4.refx.ratingunit.Changed.v1"
          }
        },
        "additionalProperties": false
      },
      "Data": {
        "required": [
          "ratingUnits"
        ],
        "type": "object",
        "properties": {
          "ratingUnits": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RatingUnit"
            }
          }
        },
        "additionalProperties": false
      },
      "RatingUnit": {
        "required": [
          "ratingUnitNumber"
        ],
        "type": "object",
        "properties": {
          "ratingUnitNumber": {
            "minLength": 1,
            "type": "string",
            "example": 5010000141
          }
        },
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://login.microsoftonline.com/99cf3097-888d-4695-bf1f-f3856b777551/oauth2/v2.0/token",
            "scopes": {
              "0eb0f66f-85af-47ca-872c-29b161bf36b7/.default": "Reads the Weather forecast"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "oauth2": [ ]
    }
  ]
}

Describe the bug you're encountering

I am trying to get an Authorization token in Swagger-UI from Microsoft's Entra ID (formerly known as Azure AD) using client credentials flow. However, I get a 400. because Swagger-UI is not passing the client_id and client_secret in the request body, which Entra ID requires. Edit - Entra ID will also accept a Basic Authorization header.

An older issue was having the same problem but using Auth0. #4533
Edit, one month later, I just found another duplicate #5104

To reproduce...

Steps to reproduce the behavior:

  1. Go to https://editor.swagger.io/
  2. Paste my swagger.json above
  3. Press the Authorize button
  4. Enter client_id abc and client_secret def
  5. Press the Authorize button
  6. In Browser dev tools, click on the request to login.microsoftonline.com which has thrown a 400 (we're gonna ignore the CORS error for now, that's another issue)
  7. Click on Request - notice that only grant_type and scope have been sent in the request - client_id and client_secret are missing. (They are instead sent in an Authorization header).
    N.B. I have also reproduced this by running latest v5.15.0 of Swagger-UI on my localhost.

Expected behavior

Please add a configuration value to allow us to send the client_id and client_secret in the request body instead of in the Authorization header (current behaviour).

Screenshots

image

Related issue: domaindrivendev/Swashbuckle.AspNetCore#2544

@PSanetra
Copy link

PSanetra commented May 8, 2024

I stumbled over this issue in context of Microsoft Entry ID, too.
The client_id and client_secret are not passed as form parameters. Instead the Authorization header is used. This is genereally also supported by Microsoft:

The client_secret parameter documentation mentions:

The Basic auth pattern of instead providing credentials in the Authorization header, per RFC 6749 is also supported.

https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-client-creds-grant-flow#first-case-access-token-request-with-a-shared-secret

The true cause of this issue seems to be that Microsoft seems to have stopped support for the client_credentials flow to be called from a website.

You can confirm this by trying out the following curl requests:

Token request without origin header

> curl https://login.microsoftonline.com/${YOUR_TANENT_ID}/oauth2/v2.0/token \
  -d 'grant_type=client_credentials' \
  -d "scope=${YOUR_CLIENT_ID}/.default" \
  -d "client_id=${YOUR_CLIENT_ID}" \
  -d "client_secret=${YOUR_CLIENT_SECRET}"
{"token_type":"Bearer","expires_in":3599,"ext_expires_in":3599,"access_token":"...your_token..."}

Token request with origin header like a request would be issued in a browser

> curl -v https://login.microsoftonline.com/${YOUR_TANENT_ID}/oauth2/v2.0/token \
  -H 'Origin: http://localhost:8080' \
  -d 'grant_type=client_credentials' \
  -d "scope=${YOUR_CLIENT_ID}/.default" \
  -d "client_id=${YOUR_CLIENT_ID}" \
  -d "client_secret=${YOUR_CLIENT_SECRET}"
[...]
< HTTP/2 400
[...]
{"error":"invalid_request","error_description":"AADSTS9002326: Cross-origin token redemption is permitted only for the 'Single-Page Application' client-type. Request origin: 'http://localhost:8080'. Trace ID: [...] Correlation ID: [...] Timestamp: [...]","error_codes":[9002326],"timestamp":"[...]","trace_id":"[...]","correlation_id":"[...]","error_uri":"https://login.microsoftonline.com/error?code=9002326"}

I don't think this issue can be solved by swagger-ui. Microsoft would need to enable support for client_credentials flow from browsers again.

@mattfrear
Copy link
Author

mattfrear commented May 8, 2024

Hi @PSanetra thank you for adding your findings. Nice work figuring out that Origin header is the issue!

I wonder if there is some magic value of the Origin header which it will accept?

I don't think this issue can be solved by swagger-ui.

I agree it's not a Swagger UI issue.

Microsoft would need to enable support for client_credentials flow from browsers again.

I wonder if there is some config in our Entra ID App Registration's manifest which would allow this?

@PSanetra
Copy link

PSanetra commented May 8, 2024

@mattfrear good question if there is some configuration option for this. I would be interested too.

For now I will go with simple Authorization header with Bearer scheme in swagger ui and show some description how to get the client_credentials token via curl as a workaround.

@mattfrear
Copy link
Author

Closing this because it's not a Swagger UI issue, it's caused by Entra ID rejecting client_credentials requests which have an Origin header.

@mattfrear mattfrear reopened this May 8, 2024
@mattfrear mattfrear closed this as not planned Won't fix, can't repro, duplicate, stale May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants