api-manager icon indicating copy to clipboard operation
api-manager copied to clipboard

Content-Type is changed by API-Manager when the backend is secured by OAuth 2.0

Open niranRameshPeiris opened this issue 3 years ago • 1 comments

Description:

When we have secured the backend of an API using OAuth 2.0, Content-Type of the form data parameters will be automatically changed from application/json to text/plain.

Steps to reproduce:

  • Start two APIM servers. (One as the backend, the other as the APIM server)
  • Create an API in backend-APIM. (API1)
  • Create another API in server-APIM. (API2)
  • Set the URL of the API1 as the backend of the API2.
  • Configure OAuth 2.0 security for the backend.
  • Inoke the API1 using postman. The sample body should be as below.
--form 'resumeDocumentInfo="{
  \"filename\":\"test.pdf\",
  \"originalType\":\"Pdf\",
  \"ownerId\":\"test\",
  \"ownerType\":\"GlobalParseAPI\"
}";type=application/json' \
--form 'resumeDocument=@"/path/to/file"'

By using wire logs, we were able to observe that, the content type of the resumeDocumentInfo will be changed from application/json to text/plain when reaching the backend. Please find the wire logs below. Request from Client to the APIM.

[2022-04-19 18:21:38,022] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "POST /authtest/v1/resume-documents HTTP/1.1[\r][\n]"
[2022-04-19 18:21:38,023] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "accept: */*[\r][\n]"
[2022-04-19 18:21:38,023] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Authorization: Bearer eyJ4NXQiOiJOVGRtWmpNNFpEazNOalkwWXpjNU1tWm1PRGd3TVRFM01XWXdOREU1TVdSbFpEZzROemM0WkEiLCJraWQiOiJNell4TW1Ga09HWXdNV0kwWldObU5EY3hOR1l3WW1NNFpUQTNNV0kyTkRBelpHUXpOR00wWkdSbE5qSmtPREZrWkRSaU9URmtNV0ZoTXpVMlpHVmxOZ19SUzI1NiIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJhZG1pbiIsImF1dCI6IkFQUExJQ0FUSU9OIiwiYXVkIjoiRmxJQW1QaHc2d3NUZjZ4M0lxanAxU2xDcVlvYSIsIm5iZiI6MTY1MDM3ODA2NCwiYXpwIjoiRmxJQW1QaHc2d3NUZjZ4M0lxanAxU2xDcVlvYSIsInNjb3BlIjoiZGVmYXVsdCIsImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0M1wvb2F1dGgyXC90b2tlbiIsImV4cCI6MTY1MDM4MTY2NCwiaWF0IjoxNjUwMzc4MDY0LCJqdGkiOiJlYzE3MDIxOC00NDRiLTRjZjctOTBlNS1kNzljNWZhYTIyZjIifQ.CmwfiILihoDvZ8BtPhMUif9f6lLLdFMyYqFJO6puVEhSWaK8FBiyWqT3dqgvLqkcjaalltUmntsMC20k8OfgFgelPcYoTSweVg8FLTcNqsC5yOesk8AqVLeUT7dFIgDp8ElcqwCn_T0eQ0aPe_bful-n_OdzlSOgx-NcD57nk5-rPW3vCceDsAGbEy6rdm8nd07tRLNaC3pUp1Y431mnML_ekLUHcb-M-DgzwNYvJxAxr3fhIdHYa7v5pWWnGMCTfeg9B1Bx_wSErLgIAhqkLjEvHFRfSpcG4Q6ewM72jS3NkPa2Vv1qh_9N5YqSvGb-rGtm2PqaBa3Q7boTl8uWaQ[\r][\n]"
[2022-04-19 18:21:38,023] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "User-Agent: PostmanRuntime/7.28.4[\r][\n]"
[2022-04-19 18:21:38,023] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Postman-Token: 9af0ef96-f0c6-416d-9ee3-30d902cd10df[\r][\n]"
[2022-04-19 18:21:38,023] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Host: localhost:8243[\r][\n]"
[2022-04-19 18:21:38,024] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Accept-Encoding: gzip, deflate, br[\r][\n]"
[2022-04-19 18:21:38,024] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Connection: keep-alive[\r][\n]"
[2022-04-19 18:21:38,024] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Content-Type: multipart/form-data; boundary=--------------------------637560373573055154218371[\r][\n]"
[2022-04-19 18:21:38,024] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Content-Length: 434[\r][\n]"
[2022-04-19 18:21:38,024] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "[\r][\n]"
[2022-04-19 18:21:38,024] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "----------------------------637560373573055154218371[\r][\n]"
[2022-04-19 18:21:38,024] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Content-Disposition: form-data; name="resumeDocumentInfo"[\r][\n]"
[2022-04-19 18:21:38,024] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Content-Type: application/json[\r][\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "[\r][\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "{[\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "  "filename":"test.pdf",[\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "  "originalType":"Pdf",[\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "  "ownerId":"test",[\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "  "ownerType":"GlobalParseAPI"[\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "}[\r][\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "----------------------------637560373573055154218371[\r][\n]"
[2022-04-19 18:21:38,025] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "Content-Disposition: form-data; name="resumeDocument"; filename=""[\r][\n]"
[2022-04-19 18:21:38,026] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "[\r][\n]"
[2022-04-19 18:21:38,026] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "[\r][\n]"
[2022-04-19 18:21:38,026] DEBUG - wire HTTPS-Listener I/O dispatcher-1 >> "----------------------------637560373573055154218371--[\r][\n]"

Request from APIM to the Backend.

[2022-04-19 18:21:38,071] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "POST /backend/v1/resume-documents HTTP/1.1[\r][\n]"
[2022-04-19 18:21:38,071] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Authorization: Bearer eyJ4NXQiOiJNell4TW1Ga09HWXdNV0kwWldObU5EY3hOR1l3WW1NNFpUQTNNV0kyTkRBelpHUXpOR00wWkdSbE5qSmtPREZrWkRSaU9URmtNV0ZoTXpVMlpHVmxOZyIsImtpZCI6Ik16WXhNbUZrT0dZd01XSTBaV05tTkRjeE5HWXdZbU00WlRBM01XSTJOREF6WkdRek5HTTBaR1JsTmpKa09ERmtaRFJpT1RGa01XRmhNelUyWkdWbE5nX1JTMjU2IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJhZG1pbiIsImF1dCI6IkFQUExJQ0FUSU9OIiwiYXVkIjoidFNyQzh1ZXl5WUxUUzVUak5sY3JoejRQVE9RYSIsIm5iZiI6MTY1MDM3ODA2OSwiYXpwIjoidFNyQzh1ZXl5WUxUUzVUak5sY3JoejRQVE9RYSIsInNjb3BlIjoiZGVmYXVsdCIsImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0NFwvb2F1dGgyXC90b2tlbiIsImV4cCI6MTY1MDM4MTY2OSwiaWF0IjoxNjUwMzc4MDY5LCJqdGkiOiIyNzYxMmMxYi00Yjk1LTRmNTgtYTZkNi1hNjQ2MzhhYzFkMDAifQ.C0xJE7jXqrziCQ8nXciQU9i4daY0UHWXDvcL6g_FRp37q9EJJgzNS_cEf85bwssdS9_X-toJJnxPnHRKHWvzZIFLNICCnKO3rRi3wn-h1hPtOjYS7VlLJ7Yktdrp2hn9CIgiOMRgCDZnoITAbwHZKPlHjEcy5fNV4dqcozOucO6y3WcgrBgHbGGG2vpK-UwGYZvXaDPNRNy_I_SNEhMbm8sycWSbbo8Cw8YzzVCCVdFVP9rLF7s7EMVitTbWTSI5_32NJzCNAFSL7JlEsLLSgm0t4sDF04hKowgRSR12peQekshMFT2ssowsQ519qili-T78-qnIlvF5fctKpCpC4A[\r][\n]"
[2022-04-19 18:21:38,072] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "activityid: 90fa7f5b-ecd9-480a-9f5b-7f6bfc51ccd5[\r][\n]"
[2022-04-19 18:21:38,072] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Postman-Token: 9af0ef96-f0c6-416d-9ee3-30d902cd10df[\r][\n]"
[2022-04-19 18:21:38,072] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Accept-Encoding: gzip, deflate, br[\r][\n]"
[2022-04-19 18:21:38,072] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "accept: */*[\r][\n]"
[2022-04-19 18:21:38,072] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Type: multipart/form-data; charset=UTF-8; boundary=MIMEBoundary_f517263f931d7d6f85b3ca6e0b8e1af43466e5b29b07bd39[\r][\n]"
[2022-04-19 18:21:38,072] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Transfer-Encoding: chunked[\r][\n]"
[2022-04-19 18:21:38,072] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Host: localhost:8244[\r][\n]"
[2022-04-19 18:21:38,072] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Connection: Keep-Alive[\r][\n]"
[2022-04-19 18:21:38,073] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "User-Agent: Synapse-PT-HttpComponents-NIO[\r][\n]"
[2022-04-19 18:21:38,073] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"
[2022-04-19 18:21:38,073] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "251[\r][\n]"
[2022-04-19 18:21:38,073] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "--MIMEBoundary_f517263f931d7d6f85b3ca6e0b8e1af43466e5b29b07bd39[\r][\n]"
[2022-04-19 18:21:38,073] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Disposition: form-data; name="resumeDocumentInfo"[\r][\n]"
[2022-04-19 18:21:38,073] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Type: text/plain; charset=US-ASCII[\r][\n]"
[2022-04-19 18:21:38,073] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Transfer-Encoding: 8bit[\r][\n]"
[2022-04-19 18:21:38,074] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"
[2022-04-19 18:21:38,074] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "{[\n]"
[2022-04-19 18:21:38,074] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "filename":"test.pdf",[\n]"
[2022-04-19 18:21:38,074] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "originalType":"Pdf",[\n]"
[2022-04-19 18:21:38,074] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "ownerId":"test",[\n]"
[2022-04-19 18:21:38,075] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "  "ownerType":"GlobalParseAPI"[\n]"
[2022-04-19 18:21:38,075] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "}[\r][\n]"
[2022-04-19 18:21:38,075] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "--MIMEBoundary_f517263f931d7d6f85b3ca6e0b8e1af43466e5b29b07bd39[\r][\n]"
[2022-04-19 18:21:38,075] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Disposition: form-data; name="resumeDocument"; filename=""[\r][\n]"
[2022-04-19 18:21:38,075] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Type: text/plain; charset=ISO-8859-1[\r][\n]"
[2022-04-19 18:21:38,075] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "Content-Transfer-Encoding: binary[\r][\n]"
[2022-04-19 18:21:38,075] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"
[2022-04-19 18:21:38,076] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"
[2022-04-19 18:21:38,076] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "--MIMEBoundary_f517263f931d7d6f85b3ca6e0b8e1af43466e5b29b07bd39--[\r][\n]"
[2022-04-19 18:21:38,076] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"
[2022-04-19 18:21:38,076] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "0[\r][\n]"
[2022-04-19 18:21:38,076] DEBUG - wire HTTPS-Sender I/O dispatcher-1 << "[\r][\n]"

Affected product version:

APIM-4.0.0

Solution:

This can be resolved by applying the change suggested here. [1]

[1] - https://github.com/wso2-support/carbon-apimgt/pull/3700

niranRameshPeiris avatar Apr 21 '22 09:04 niranRameshPeiris

Not Reproducible in WSO2 API Manager 4.6.0

This issue has been fixed and is not reproducible in WSO2 API Manager 4.6.0.

Root Cause

The OAuthMediator was content-aware by default, causing Apache Synapse to parse and rebuild messages, which modified Content-Type headers in multipart boundaries.

Fix Applied

@Override
public boolean isContentAware() {
    return false;  // Prevents message modification
}

File: components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/oaut
h/OAuthMediator.java (Lines 133-136)

Result

By disabling content-aware behavior, the mediator becomes pass-through, preserving original Content-Type headers.
Multipart form-data fields with Content-Type: application/json now maintain their type when forwarded to
OAuth-secured backends.

Verified: Code analysis confirms fix is present in APIM 4.6.0
Status: ✅ Fixed

🤖 Generated with [Claude Code](https://claude.ai/code)

ranuka-laksika avatar Nov 24 '25 06:11 ranuka-laksika